.so qmacs
.sp 2i
.ce 10
LIFELINES QUICK REFERENCE GUIDE
Version 2.3.6
Thomas T. Wetmore IV
2 Barton Street
Newburyport, MA 01950 USA
508-465-3220
thomas.wetmore@att.com
20 January 1994
.ce 0

INTRODUCTION
.P
LifeLines is a genealogy program that runs on UNIX systems.
It maintains genealogical (person, family, source, event and other)
records in a database, and generates reports from those records.
There are no practical limits on the number of persons or
families or other records that can be stored in a LifeLines database,
nor are there restrictions on the amount or kinds of data that can be
stored.
LifeLines does not contain built-in reports.
Instead, it provides a report generation subsystem that allows you to
program your own reports and charts.
LifeLines uses the terminal independent features of UNIX to provide a
panels and menu based user interface that is simple and intuitive.

.ne 2i
INSTALLATION
.P
The distribution package for LifeLines contains an executable
program, report programs, and release documentation.
The executable command is "lines," the LifeLines program
(you may change its name).
To install LifeLines, place the program in a directory
in your execution path.
The report programs generate a wide variety of standard genealogical
reports, and can be modified to your own tastes.

.ne 2i
STARTING LIFELINES AND CREATING DATABASES
.P
Start LifeLines with the command:

    \f(CWlines\fR \fIpath\fR

where \fIpath\fR is the name of a directory that holds, or
will hold, a LifeLines database.
If LifeLines finds a database there, it opens the database and
takes you to the program's main menu.
If the database doesn't exist, LifeLines asks whether it should
create it, and if you answer yes, does so.
You may create as many LifeLines databases as you like, but only one
can be accessed by LifeLines at any one time.

.ne 2i
INTRODUCTION TO GEDCOM
.P
LifeLines records are stored in GEDCOM format; you must organize, edit
and maintain your data in this format.
GEDCOM is a standard that defines a file format for moving genealogical
data between computer systems; LifeLines uses this same format for
structuring its database.
This approach allows LifeLines to provide a structured yet flexible
method for storing all data you wish to record.
There are almost no restrictions on the format, amount or type
of information you can store in a LifeLines database.
.P
LifeLines does not use forms or screens for entering or changing data;
instead you use a screen editor to directly edit the data records.
This means you must understand the GEDCOM format, and be able to edit
data in GEDCOM format, before you can use LifeLines.
The GEDCOM format is so logical and simple, however, that the rest of
introduction should provide all you need to know to use GEDCOM in
LifeLines.
.P
Here is an example GEDCOM person record:

.ne 1i
  \f(CW0 @I25@ INDI
  1 NAME Thomas Trask /Wetmore/ Sr
  1 SEX M
  1 BIRT
    2 DATE 13 March 1866
    2 PLAC St. Mary's Bay, Digby County, Nova Scotia
    2 SOUR Social Security application
  1 NATU
    2 NAME Thomas T. Wetmore
    2 DATE 26 October 1888
    2 PLAC Norwich, New London County, Connecticut
    2 AGE 22 years
    2 COUR New London County Court of Common Pleas
    2 SOUR court record from National Archives
  1 DEAT
    2 NAME Thomas Trask Wetmore
    2 DATE 17 February 1947
    2 PLAC New London, New London County, Connecticut
    2 AGE 80 years, 11 months, 4 days
    2 BIRT
      3 DATE 13 March 1866
      3 PLAC Plympton, Nova Scotia
    2 OCCU Antiques Dealer
    2 FATH
      3 NAME Daniel L. Wetmore
    2 MOTH
      3 NAME Mary A. Doty
    2 CAUS Heart Attack
    2 SOUR New London Death Records
  1 FAMC @F11@
  1 FAMS @F6@
  1 FAMS @F12@\fR
.P
A GEDCOM record is made up of lines.
Each line has a level number and a tag, and
most lines have a value following the tag.
The first line in every GEDCOM record has a cross-reference
index between the level number and the tag.
.P
Level numbers allow the data to be structured to any degree of
detail;
lines with higher level numbers expand on lines with lower numbers.
Tags are uppercase code words that specify the kind of information on
the rest of the line, or on the higher numbered lines that follow. 
The information after the tag, if any, is the value of the line.
.P
The first line in any GEDCOM record indicates its type.
There are two record types in LifeLines databases,
person records and family records.
The first line in a person record has the tag INDI; the first
line in a family record has the tag FAM.
These are the only level 0 lines found in LifeLines records, and
the only lines with a cross-reference index, an internal reference
key used to link records together.
Cross-reference indexes are bracketed by @ characters.
.P
The first line in the example identifies it as a person record; other
records can refer to it by using the cross-reference index I25.
.P
The second line in the example has the person's name.
Each person record in a LifeLines database must have at least one NAME
line, and its value must be in GEDCOM name format.
This format allows names to be as long as needed, but the surname, which
can be placed anywhere in the name, must be bracketed by forward slashes.
If you don't know a person's surname, you can use /____/ or /UNKNOWN/ or
even //.
A person may have any number, including zero, given names and/or initials.
.P
The next line in the example specifies the person's sex.
LifeLines doesn't require a SEX line, but you should include it.
If not there, the person can't be made a spouse or parent in a family.
The value of the line should be M or F if the sex is known, or U or ? if not.
.P
The record also contains three events:  birth, naturalization,
and death.
An event begins with a level 1 line whose tag indicates the
event type.
For example, BIRT is the tag for a birth event.
.P
Events usually have at least DATE and PLAC lines and often SOUR lines.
The DATE and PLAC lines give the date and place of the event.
The value of a LifeLines DATE line is free format, although the GEDCOM
standard is more strict.
The value of a PLAC line is generally a comma-separated list of
geopolitical units, starting with the most specific, ending with the
most general.
The SOUR line indicates the source of your information about the
event.
.P
The naturalization event (with tag NATU) shows a few other lines.
The NAME line gives the person's name as recorded in the source
(note that only NAME lines at level 1 must follow GEDCOM format).
The AGE line gives the person's age at the time of the event.
The COUR line indicates the court where naturalization occurred.
.P
The final event is a death event (tag DEAT).
In this example the information came from a primary death record.
The death event contains a birth event as a sub-event, because the
death record contained information about the deceased's birth.
The primary death record also contained information about the
deceased's parents, occupation and cause of death; note how this
information has also been placed in the GEDCOM record.
.P
At the end of the example record are three lines that
reference family records.
A FAMC line refers to the family record that the person
belongs to as a child; its value is the cross-reference index value of
that family.
A FAMS line refers to a family record that the person
belongs to as a spouse or parent.
.P
When using LifeLines to edit a person, you will not be able to change
the cross reference values on the INDI, FAMC or FAMS lines; these are
maintained by LifeLines.
.P
Here is an example family record:

.ne 9
  \f(CW0 @F6@ FAM
  1 HUSB @I25@
  1 WIFE @I26@
  1 MARR
    2 DATE 31 March 1891
    2 PLAC New London, New London County, Connecticut
    2 SOUR New London Vital Records
  1 CHIL @I27@
  1 CHIL @I17@\fR

The FAM line assigns the family a cross-reference index of F6.
The record contains HUSB and WIFE lines that refer to the two
spouses/parents.
This record also contains a marriage event (tag MARR).
It also contains two CHIL lines that refer to two children in
the family.
When editing marriage records, you cannot change the cross reference
values on the FAM, HUSB, WIFE, or CHIL lines; these are maintained by
LifeLines.
.P
When you create new records for your database, you are free to invent
tags and structure your data in any way you see fit.
However, it is good practice to use the standard GEDCOM tags and value
formats.
Within person records, LifeLines insists that you use 1 NAME and 1 SEX
lines with their special meanings.
Also, LifeLines assumes that you will use 1 BIRT, 1 DEAT, 1 CHR, and
1 BURI lines for birth, death, baptism and burial events, respectively.
In family records, LifeLines assumes you will use the 1 MARR event for
marriage events.
Within person records, you are not allowed to use 0 INDI, 1 FAMC or 1
FAMS lines since these are used to maintain linkage information.
Within marriage records, you are not allowed to use 0 FAM, 1 HUSB, 1
WIFE or 1 CHIL lines.
.P
Note: the indentation shown in the example GEDCOM records is not
necessary, and not part of the GEDCOM format.
Whenever LifeLines prepares records for you to edit it always indents
the records, making them easier to read and understand.
You do not need to follow this indentation scheme when you edit the
records.
All indentation is removed from the data before it is stored in the
database.

.ne 2i
MAIN MENU
.P
After LifeLines opens an existing database, or creates a new one,
it presents you with the main menu:

.ne 9
  Please choose an operation:
    b  Browse the persons in the database
    a  Add information to the database
    d  Delete information from the database
    r  Generate reports from the database
    u  Miscellaneous utilities
    q  Quit and return to UNIX

Select an operation by striking the proper selection letter.
.P
The browse operation lets you browse the
database and perform many operations on the data.
The add operation lets you add new information, and the delete
operation removes information.
The generate reports operation reads report programs and generates
output reports.
The miscellaneous utilities operation provides such things
as backup and restore.
The quit operation closes the database and returns to UNIX.
.P
The browse operation deserves special mention, because it provides
a rich environment for searching, viewing, adding, modifying, merging
and deleting information in the database.
You will find that you operate from the browsing mode most of
the time.

.ne 2i
ENTERING THE FIRST PERSON
.P
Normally you add persons to the database from the browsing mode, but
when entering the first person there is no one in the database
to browse to.
To add the first person to a LifeLines database, you must select the add
operation from the main menu.
You will be prompted with the add menu (described later).
Strike p to add a person.
LifeLines creates a template of a GEDCOM person record,
and puts you in a screen editor to edit the template.
The template is:

.ne 10
  0 INDI
  1 NAME Fname /Surname/
  1 SEX MF
  1 BIRT
    2 DATE
    2 PLAC
    2 SOUR
  1 DEAT
    2 DATE
    2 PLAC
    2 SOUR

Edit this template to create new person's record.
Change the name to the person's real name. 
Assign the person's sex by deleting either M or F
(if you don't know the sex, use the value U or ?).
Fill out the birth and death events as best you can.
If the person is alive, remove the death event.
Remove any DATE and PLAC lines you do not have the information for.
.P
The template provides lines for one birth and one death event.
You can expand the record with other events (even more birth or
death events) and lines.
Indentation makes it easier to read and edit the record, but isn't
necessary (leading white space is not retained in the database
record).
.P
Here is how I might edit the template if I were creating a record for
myself:

  0 INDI
  1 NAME Thomas Trask /Wetmore/ IV
  1 SEX M
  1 BIRT
    2 DATE 18 December 1949
    2 PLAC New London, New London County, Connecticut
    2 SOUR Birth Certificate
  1 OCCU Software Engineer
  1 RESI
    2 DATE 1982 to 1993
    2 PLAC Newburyport, Essex County, Massachusetts
    2 ADDR 2 Barton Street
      3 CONT Newburyport, MA 01950
.P
When you edit a person record, don't add INDI, FAMC or FAMS lines.
These lines establish a person's links to family records, and LifeLines
creates and maintains this information through specific commands.
.P
When you finish editing and leave the editor, you
automatically return to LifeLines.
If you made an error (eg, didn't use proper level numbers, or didn't
follow the GEDCOM name convention), LifeLines displays an error message,
and asks if you want to re-edit the record.
If you don't, LifeLines doesn't add the person to the database.
.P
When the record is in proper format, LifeLines asks if
you are sure you want to add the person to the database.
If you answer yes, the person is added; if you answer
no, the person isn't.
In both cases LifeLines returns to the main menu.

.ne 2i
SCREEN EDITORS AND ENVIRONMENT VARIABLES
.P
The default screen editor for LifeLines is "vi."
This can be overridden by using the ED or EDITOR
environment variables.
For example, if you prefer the "emacs" screen editor, you can add
the line:
	
        ED=emacs

to your login profile file.
.P
There are four other environment variables used by LifeLines.
They are LLDATABASES, LLARCHIVES, LLPROGRAMS and LLREPORTS.
LLDATABASES and LLPROGRAMS are UNIX path list variables.
LLDATABASES can be set to a list of directory locations that hold
LifeLines databases.
When you execute the LifeLines programs these directories will be
searched in turn for the database mentioned on the command line.
For example,

	LLDATABASES=.:/usr/ttw4/LifeLines/Databases

indicates that databases should be searched for first in the current
directory, and if not found there, searched for in:

	/usr/ttw4/LifeLines/Databases

The environment variable LLPROGRAMS is used in the same way, but to
specify the search path for report programs (described later).
.P
LLARCHIVES and LLREPORTS can each be set to specify a single
directory.
LLARCHIVES can be set to the directory where you want all database
backup files to be stored, and LLREPORTS can be set to the directory
where all generated reports will be placed.
.P
You can always override these environment variables by specifying file
and directory names as absolute or as a relative file names.
You are not required to use any of these environment variables; their
default values are all the current directory.

.ne 2i
BASICS OF BROWSING
.P
You will use the browsing modes of LifeLines most of the time.
When in these modes you can quickly search for or browse through the
persons and families in the database.
When you find a person or family you are interested in, you can
quickly edit their records.
.P
The browsing modes also allow you to add new persons and families to
the database, add spouses to families, add children to families,
swap the order of spouses and children, merge persons and families,
and perform other operations.
The browsing mode also lets you remove spouses from families and
remove children from families.
.P
There are six different browsing modes.
The person and family modes concentrate on a single person and
family, respectively.
The list mode allows you to browse through a list of persons.
The pedigree mode shows a four generation pedigree, the person tandem
mode shows two persons at once, and the family tandem mode shows two
families at once.

.ne 2i
IDENTIFYING A PERSON OR LIST OF PERSONS TO BROWSE
.P
To enter the browsing modes from the main menu, you strike the b key.
LifeLines asks you to identify a person or list of persons to browse to:

.ne 2
  Please identify person or persons to browse to.
  Enter name, key or list:

At this point you will either enter a name or partial name, or a key
value, or the name of a previously defined list of persons (described
later), and then strike enter/return.
.P
LifeLines gives you wide flexibility in how you enter names.
You may enter a name in upper or lower case or in any
combination.
You may leave out all but the first given name, and, for given
names, you may leave out any letters except the first.
You may leave vowels out of the surname, and after enough consonants
have been typed to determine the name's SOUNDEX code (usually four
or five), you can leave them out too.
You must separate the given names from the surname by a slash,
and if you enter given names after the surname (as in
Chinese names), or any modifiers (such as Jr, Sr, IV, etc.),
they must be separated from the surname by another slash.
Here are a number of ways I can enter my name:

  Thomas Trask /Wetmore/ IV
  Thomas T /WETMORE/ IV
  t t/wEtMrE/i
  TH TR/WETMORE
  t/wtmr/iv
.P
You may browse for the list of all persons who have the same surname by
using the * character as the first initial.
For example:

  */Wetmore

will match all persons with surname Wetmore.
.P
After you enter a name, LifeLines searches for persons who
match the name.
There are three possibilities: no one matches; one person
matches; or more than one person matches.
In the first case LifeLines writes the message:

  There is no one in the database with that name.

and leaves you in the main menu.
.P
In the second case (one person matches) LifeLines enters the person
browsing mode (see below) and displays the matched person.
.P
In the third case (more than one match) LifeLines enters the list
browsing mode (see below), which allows you to browse up and down
through all the person who matched the name.
.P
You may also identify a person by entering his or her internal key
number.
This is the number shown after each person's name in menus and
display panels.
If LifeLines finds a person with the key value you provide, LifeLines
enters the person browsing mode displaying that person.
.P
The browse command 'b' is also available from most of the browsing
sub-modes.

.ne 2i
`ZIP' IDENTIFYING A NEW PERSON
.P
A number of the LifeLines operations ask you to identify a person,
not for the purpose of browsing, but for the purpose of completing
some operation you have asked for.
For example, when you add a child to a family, LifeLines may have to
ask you to identify the child.
When this happens a small panel will pop up that asks you to identify a
person.
You can respond by typing a name or key exactly as you would for
the 'b' command.
.P
If no one matches, LifeLines will return to the pervious browsing
state.
If one person matches LifeLines displays something like:

.ne 3
  Is this the person?  Enter 1 if so
    1  Thomas Trask Wetmore IV, b. 1949, Conn. (1)
    q  Return from this list

If you strike 1, uses that person in the operation.
If you strike q, LifeLines asks whether you want to enter another
name.
.P
In the third case (more than one match) LifeLines types something like:

.ne 8
  Please choose from among these persons
    1  Thomas Trask Wetmore V, b. 1982, Mass. (5)
    2  Thomas Trask Wetmore IV, b. 1949, Conn. (1)
    3  Thomas Trask Wetmore III, b. 1925, Conn. (6)
    4  Thomas Trask Wetmore Jr, b. 1896, Conn. (11)
    5  Thomas Trask Wetmore Sr, b. 1866, N.S. (23)
    6  Thomas Trask Wetmore, b. 1826, poss N.S. (42)
    q  Return from this list

If you see the person you want, select him or
her by choosing the right number.
If you don't want to select one of them, strike q,
and LifeLines asks whether you want to enter another name.
.P
When LifeLines creates a list of names for you to select from, it
tries to add extra information to the name; this helps determine
which name to choose, and is important in databases where
many persons have the same name.
LifeLines places the person's internal key number at the end of each
menu line; this can also be helpful in large databases.
.P
Sometimes so many persons match a name that LifeLines can't display
them all at once.
In this case LifeLines shows you a partial list and provides commands
to display other parts of the list.
.P
You can also identify a person by entering his or her internal key
number.
This is the number shown after each person's name in menus and
display panels.
.P
Some of the browse modes provide the 'z' command, which allows you to
browse to a new person using the zip style of identification rather
than the 'b' style of identification.
This is an artifact of a major change in the system, and is likely to
change.

.ne 2i
BROWSE DISPLAY BASICS
.P
The screen display for each browsing mode is made up of panels.
At the bottom of each display is a message panel that is used for
short, one line messages.
Each display contains one or two data panels that show information
from the database.
And each display has a panel that holds the menu of operations
available from that browsing mode.

.ne 2i
PERSON BROWSE MODE
.P
After you identify a person to browse to, LifeLines enters the person
browse mode.
The top panel in the display gives basic information about the person.
For example:

.ne 6
  Thomas Trask WETMORE Sr (25)
    born: 13 March 1866, St. Mary's Bay, Digby County, Nova Scotia
    died: 17 February 1947, New London, New London County, Connecticut
    father: Daniel Lorenzo WETMORE, b. 1821, N.S., d. 1903, Conn. (48)
    mother: Mary Ann DOTY, b. 1824, N.S., d. 1897, Conn. (59)
    spouse: Margaret Ellen KANEEN, b. 1855, Eng., d. 1900, Conn. (26)

The bottom panel provides a menu of commands:

.ne 8
  Please enter the next person browse operation:
   e  Edit the person     g  Browse to family   p  Show pedigree
   f  Browse to father    u  Browse to parents  n  Create new person
   m  Browse to mother    b  Browse to persons  a  Create new family
   s  Browse to spouse/s  h  Add as spouse      x  Swap two families
   c  Browse to children  i  Add as child       t  Enter tandem mode
   o  Browse to next sib  r  Remove as spouse   z  Browse to person
   y  Browse to prev sib  d  Remove as child    q  Return to main menu

These commands perform a wide variety of functions.

e - Edit the person
.P
This command lets you edit the person's GEDCOM record.
LifeLines writes the editable parts of the record to a file, and then
puts you into a screen editor.
When you return from the editor, LifeLines asks if you are sure you want
to update the person;
the person is changed only if you answer yes.

f - Browse to father
.P
This command browses to the father of the person, and then
displays him.
If the father isn't in the database LifeLines doesn't change the display.

m - Browse to mother
.P
This command browses to the mother of the person, and then
displays her.
If the mother isn't there LifeLines doesn't change the display.

s - Browse to spouse/s
.P
This command browses to a spouse of the person, and then
displays the spouse.
If the person has more than one spouse, LifeLines asks you
to selects one from a list that LifeLines constructs.
If the person has no spouse, LifeLines doesn't change the display.

c - Browse to children
.P
This command browses to a child of the person, and then
displays the child.
If the person has more than one family, or has more than one child in a
family, LifeLines asks you the necessary questions to identify a specific
child.

o - Browse to next sib
.P
This command browses to the next older sibling of the person,
and then displays the sibling.
If the person has no older sibling, LifeLines doesn't change the display.

y - Browse to prev sib
.P
This command browses to the next younger sibling of the person,
and then displays the sibling.
If the person has no younger sibling, LifeLines doesn't change the display.

g - Browse to family
.P
This command browses to the family that the person is a
spouse or parent in, and then switches to family browse mode.
If the person is a spouse or parent in more than one family, LifeLines
first asks you to identify which one.
See the section on the family browse mode.
If the person is not a spouse/parent in any family, LifeLines doesn't
change the display mode or the display.

u - Browse to parents
.P
This command browses to the family that the displayed person is a
child in, and switches to family browse mode.
If the person is not a child in a family, LifeLines doesn't change the
display mode or the display.

b - Browse to person
.P
This command allows you to browse to a new person or list of persons.
LifeLines asks you to identify a new person or persons by name, key or
list name, and depending on how many persons are identified, switches
either to the list browse mode, or remains in the person browse
mode.

h - Add as spouse
.P
This command allows you to add the person as a spouse or
parent to an existing family record.
LifeLines asks the necessary questions to identify the family, and
then asks you to confirm the request.

i - Add as child
.P
This command allows you to add the person as a child
to an existing family.
The person cannot already be a child in another family.
LifeLines asks the necessary questions to identify the family, and
then asks you to confirm the request.

r - Remove as spouse
.P
This command allows you to remove the person as a spouse or
parent in an existing family record.
If the person is a spouse or parent in more than one family, LifeLines
first asks you to identify that family.

d - Remove as child
.P
This command allows you to remove the person as a child
in an existing family record.

p - Show pedigree
.P
This command shifts LifeLines into pedigree browse mode.
The person displayed in the person browse mode
becomes the "root" person in the pedigree display.
The pedigree mode displays a person and his or her direct
ancestors for the previous three generations.
See the section on the pedigree browse mode.

n - Create new person
.P
This command lets you add a new person to the database.
LifeLines creates a new person record template and puts you into
an editor to edit the record.
When you return from the editor, LifeLines asks you to confirm that
you want to add the person.
If you answer yes, the new person is added to the database and becomes
the current person.
If you answer no, the new person is not added to the database,
and LifeLines returns to the original display.

a - Create new family
.P
This command adds a new family to the database.
The new family will have the displayed person as either a
spouse/parent or as a child; LifeLines asks which you want.
If you choose to create a family with the person as a spouse/parent,
LifeLines asks you to identify the other spouse if he or she is known.
In either case LifeLines creates a family template, and places you the
selected screen editor.
When you return from the editor, LifeLines asks whether you are sure
you want to add the new family.
If you answer yes LifeLines adds the family and shifts into family
browse mode displaying the new family.
.P
Note: if the command you ran just before the a command were the n command,
and you choose to create a family with the displayed person as a
spouse/parent, LifeLines will guess that the second spouse of the family
was the person displayed just before the new person was created.
LifeLines will ask you if this is the case, and if so, will
automatically make that person the second spouse in the new family.
If this is not the case, LifeLines asks you to identify the other spouse.

x - Swap two families
.P
This command swaps (changes the chronological order) of any
two families that the displayed person belongs to as a spouse or parent.
LifeLines asks you to identify the two families that should be swapped
and then swaps them.

t - Enter tandem mode
.P
This command switches to the tandem person browse mode.
LifeLines first asks you to identify the second person.
See the section on the tandem person mode.

z - Browse to person
.P
This command allows you to zip browse to a new person.
LifeLines asks you to identify a person by name or key value, and if
you do so, browses to that person.

q - Return to main menu
.P
This command leaves the browsing mode and returns to the main
menu.

.ne 2i
LIST BROWSE MODE
.P
The list browse mode allows you to browse though a list of persons.
The display contains of a top panel that shows specific information
about one person (the "current" person) in the list; the format of
this panel is identical to the top panel in the person browse mode.
The display also holds a panel which shows the names of up to 12 members
of the list.
The current person is identified in the list with a > character
pointing to his/her name.
The display also holds a panel with the menu of available commands:

.ne 13
.nf
  Choose an operation:
   j  Move down list
   k  Move up list
   e  Edit this person
   i  Browse this person
   m  Mark this person
   d  Delete from list
   t  Enter tandem mode
   n  Name this list
   b  Browse new persons
   a  Add to this list
   x  Swap mark/current
   q  Return to main menu
.fi

j - Move down list
.P
This command moves down the list one person.

k - Move up list
.P
This command moves up the list one person.

e - Edit this person
.P
This command allows you to edit the current person.

i - Browse this person
.P
This command takes you to the person browse mode with the current
person.

m - Mark this person
.P
This command marks the current person if he/she is not marked.
If the person is marked this command unmarks him/her.
The marked person is shown with an 'x' by his/her name.
Marked persons are used with the 't' and 'x' commands (see below).

d - Delete from list
.P
The current person is removed from the browse list (not from the
database!).

t - Enter tandem mode
.P
This command takes you to the tandem person mode with the current
person and the marked person as the two persons.

n - Name this list
.P
This command allows you to give the current list a name.
Once this has been done you can quickly browse back to this list by
giving its name after you give the 'b' command from different modes.
Names can be just about any character string, but are most convenient
when short.

b - Browse new persons
.P
This command allows you to browse to a new person or list of persons.
You can identify a person or list by name, by key, or by list name.

a - Add to this list
.P
This command allows you to add more persons to the current browse list.
You can identify the new person or persons by name, key or list name,
and they are added to and name-sorted into the current list.

x - Swap mark/current
.P
This command allows you to swap the current person with the marked
person.

q - Return to main menu
.P
This command takes you back to the main menu.

.ne 2i
FAMILY BROWSE MODE
.P
The family browse mode display inforamtion about one family.
The top panel gives basic information about the family you are
currently browsing.
For example:

.ne 20
  husband: Thomas Trask WETMORE IV (1)
    born: 18 December 1949, New London, New London County, Connecticut
    died:
  wife: Luann Frances GRENDA (2)
    born: 10 July 1949, Pittsburgh, Allegheny County, Pennsylvania
    died:
  married: 1 August 1970, Governors Island, New York, New York
  children: 3

The bottom panel holds a menu of available commands:

.nf
  Please enter the next family browse operation
    e  Edit the family    s  Add spouse to family t  Enter family tandem
    h  Browse to husband  a  Add child to family  b  Browse to new persons
    w  Browse to wife     r  Remove spouse from   z  Browse to new person
    c  Browse to children d  Remove child from    q  Return to main menu
    n  Create new person  x  Swap two children
.fi

e - Edit the family    
.P
This command lets you edit the family's GEDCOM record.
LifeLines writes the editable parts of the record into
a file, and then puts you into an editor to edit that information.
When you return from the editor, LifeLines asks you whether you
are sure you want to update the family in the database.
The family is changed only if you answer yes.

h - Browse to husband  
.P
This command browses to the husband of the family, switching
to person browse mode.
If the husband is not there, LifeLines does not change the display.

w - Browse to wife     
.P
This command browses to the wife of the family, switching
to person browse mode.
If the wife is not there, LifeLines does not change the display.

c - Browse to children 
.P
This command browses to a child of the family, switching to
the person browse mode.
If the family has more than one child, LifeLines asks you to
identify a specific child.

n - Create new person    
.P
This command allows you to add a new person to the database.
LifeLines creates a new person record record and puts you into
an editor to edit the record.
When you return from the editor, LifeLines asks you to confirm that
you want to add the person to the database.
If you answer yes, the new person is added to the database.
If you answer no, the new person is not added to the database.
In both cases LifeLines then re-displays the original family.

s - Add spouse to family
.P
This command allows you to add a spouse to the family.
LifeLines asks you to identify the new spouse.
.P
Note: if the command you ran just before the s command were the n command,
LifeLines will guess that the new spouse for the family is the person just
created.
LifeLines will ask you if this is the case, and if so, will
make that person the second spouse in the family.

a - Add child to family
.P
This command adds a child to the family.
LifeLines asks you to identify the new child.
.P
Note: if the command you ran just before the a command were the n command,
LifeLines will guess that the new child for the family is the person just
created.
LifeLines asks you if this is the case, and if so,
adds that child to the family.
If the family already has at least one child, LifeLines asks where to
place the new child in the family.

r - Remove spouse from  
.P
This command removes a spouse from the family.
LifeLines asks you to identify which spouse should be removed, and, if
you do, removes him or her.
The person is not removed from the database, just from the family.

d - Remove child from
.P
This command removes a child from the family.
LifeLines asks you to identify which child should be removed, and, if
you do, removes that child from the family.
The person is not removed from the database, just from the family.

x - Swap two children
.P
This command swaps (changes the chronological order) of any
two children in the displayed family.
LifeLines asks you to identify the two children to be swapped
and then swaps them.

t - Enter family tandem mode
.P
This command takes you to the tandem family browse mode.
LifeLines asks you to identify a second family, and after you do,
takes you to the tandem family mode and displays both the old and the
new families.

b - Browse to new persons
.P
This command allows you to browse to a new person or list of persons.
You can identify a person or list by name, by key, or by list name.
If you successfully identify a new person or persons you will switch
into the person or list browse modes.

z - Browse to new person
.P
This command allows you to zip browse to a new person.
LifeLines asks you to identify a person by name or key value, and when
you do so, browses to that person.

q - Return to main menu
.P
This command leaves the browsing mode and returns you to the main
menu.

TANDEM PERSON BROWSE MODE
.P
The tandem person browse mode displays information about two persons.
The top two panels show two persons in the same format used for the
person and list mode displays.
For example:

.ne 13
.nf
  Thomas Trask WETMORE Sr (25)
    born: 13 March 1866, St. Mary's Bay, Digby County, Nova Scotia
    died: 17 February 1947, New London, New London County, Connecticut
    father: Daniel Lorenzo WETMORE, b. 1821, N.S., d. 1903, Conn. (48)
    mother: Mary Ann DOTY, b. 1824, N.S., d. 1897, Conn. (59)
    spouse: Margaret Ellen KANEEN, b. 1855, Eng., d. 1900, Conn. (26)
-----------------------------------------------------------------------
  Thomas Trask WETMORE IV (1)
    born: 18 December 1949, New London, New London County, Connecticut
    died: 
    father: Thomas Trask WETMORE III, b. 1925, Conn. (6)
    mother: Joan Marie HANCOCK, b. 1928, Conn. (7)
    spouse: Luann Frances GRENDA, m. 1970, N.Y. (2)
.fi

The bottom panel gives the menu of available commands:

.ne 5
.nf
Please enter the next tandem browse operation
 e  Edit top person    s  Browse top spouse/s  a  Add family
 t  Browse to top      c  Browse top children  j  Merge bottom to top
 f  Browse top father  b  Browse to persons    x  Switch top/bottom
 m  Browse top mother  d  Copy top to bottom   q  Return to main menu
.fi

 e - Edit top person    
.P
This command lets you edit top person's GEDCOM record.
LifeLines writes the editable parts of the record into
a file, and then puts you into an editor to edit that information.
When you return from the editor, LifeLines asks whether you
are sure you want to update the person in the database.
The person is changed only if you answer yes.

 t - Browse to top     
.P
This command switches to the person display, making the person that
was top in the tandem display the current person.

 f - Browse top father
.P
This command replaces the top person with his/her father.

 m - Browse top mother
.P
This command replaces the top person with his/her mother.

 s - Browse top spouse/s  
.P
This command replaces the top person with his/her spouse.
If the top person has more than one spouse, LifeLines asks you to
identify the proper one.

 c - Browse top children 
.P
This command replaces the top person with one of his/her children.
If the top person has more than one child, LifeLines asks you to
identify the proper one.

 b - Browse to person   
.P
This command allows you to browse to a new person or list of persons.
LifeLines asks you to identify a new person or person by name, key or
list name, and then does as described in the section on identifying a
person.

 d - Copy top to bottom
.P
This command copies the top person into the bottom person.
A new person is not created; the same person is being displayed twice.

 a - Add family
.P
This command allows you to create a new family record;
LifeLines assumes that the two displayed persons are to become the
spouses/parents of the new family.
The two persons must be of opposite sex.

 j - Merge bottom to top
.P
This command merges the bottom person into the top person.
LifeLines combines the two person records and places you in an
editor to edit the combined record.
When you are done, and if you confirm that you still want the
merging to occur, LifeLines deletes the bottom person from the
database, and the top person is given the combined record.
See the section about merging for more information.

 x - Switch top/bottom
.P
This command interchanges the two persons in the display.

 q - Return to main menu
.P
This command leaves the browsing mode and returns to the main menu.

.ne 2i
TANDEM FAMILY BROWSE MODE
.P
The tandem family browse mode displays information about two
families.
The top two panels gives basic information about the two families you
are currently browsing.
For example:

.ne 13
  husband: Thomas Trask WETMORE IV (1)
    born: 18 December 1949, New London, New London County, Connecticut
  wife: Luann Frances GRENDA (2)
    born: 10 July 1949, Pittsburgh, Allegheny County, Pennsylvania
  married: 1 August 1970, Governors Island, New York, New York
  children: 3
-----------------------------------------------------------------------
  husband: Thomas Trask WETMORE III (6)
    born: 26 October 1925, New London, New London County, Connecticut
  wife: Joan Marie Hancock (7)
    born: 6 June 1928, New London, New London County, Connecticut
  married: 5 February 1949, New London, New London County, Connecticut
  children: 5

The bottom panel holds a menu of available commands:

.nf
  Please enter the next two family browse operation
    e  Edit top family   h  Browse to husbands  j  Merge bottom to top
    t  Browse to top     w  Browse to wives     q  Return to main menu
    b  Browse to bottom  x  Switch top/bottom

.fi

e - Edit the family    
.P
This command lets you edit the top family's GEDCOM record.
LifeLines writes the editable parts of the record into
a file, and then puts you into an editor to edit that information.
When you return from the editor, LifeLines asks you whether you
are sure you want to update the family in the database.
The family is changed only if you answer yes.

t - Browse to top
.P
This command switches to the family browse mode, making the
top family the current family.

b - Browse to bottom
.P
This command switches to the single family browse mode, making the
bottom family the current family.

h - Merge to husbands
.P
This command switches to the tandem person mode with the two husbands
of the two families as the two persons.

w - Merge to wives
.P
This command switches to the tandem person mode with the two wives
of the two families as the two persons.

 x - Switch top/bottom
.P
This command interchanges the two families in the display.

j - Merge bottom to top
.P
This command merges the bottom family into the top family.
LifeLines combines the two family records and places you in an
editor to edit the combined record.
When you are done, and if you confirm that you still want the
merging to occur, LifeLines deletes the bottom family from the
database, and the top family is given the combined record.
See the section on merging for more information.

q - Return to main menu
.P
This command leaves this browsing mode and returns you to the main
menu.

.ne 2i
PEDIGREE BROWSE MODE
.P
The pedigree browse mode displays a four-generation pedigree for
the current person.
The top panel holds the pedigree.
For example:

.ne 15
                    John WETMORE [1755-1848] (32)
              Daniel Van Cott WETMORE [1791-1881] (41)
                    Anna VAN COTT [1757-1802] (33)
        Daniel Lorenzo WETMORE [1821-1903] (48)
                    Thomas TRASK [-1836] (81)
              Hannah TRASK [1797-1829] (46)
                    Susannah PORTER [1754-] (82)
  Thomas Trask WETMORE Sr [1866-1947]  (25)
                    Samuel DOTY [1759-] (501)
              Samuel DOTY [1787-] (74)
                    Hephzibah PORTER [1764-1853] (502)
        Mary Ann DOTY [1827-1897] (59)
                    Nathan SAVERY [1748-1826] (510)
              Lydia SAVERY [1806-] (75)
                    Deidamia SABEAN [1765-1845] (511)

The bottom panel gives the menu of available commands:

.nf
  Please enter the next pedigree browse operation
   i  Browse to person   m  Browse to mother    g  Browse to family
   f  Browse to father   c  Browse to children  q  Return to main menu
.fi

i - Browse to person   
.P
This command switches to the person display mode, displaying the
person that was current in the pedigree mode.

f - Browse to father   
.P
This command browses to the father of the person, shifting the
pedigree one generation back in the father's direction.
If the father is not there, LifeLines does not change the display.

m - Browse to mother    
.P
This command browses to the mother of the person, shifting the
pedigree one generation back in the mother's direction.
If the mother is not there, LifeLines does not change the display.

c - Browse to children  
.P
This command browses to a child of the person, shifting the
pedigree one generation forward in time.
If the current person is a spouse/parent in more than one family, and/or
has more than one child, LifeLines asks you to identify the child.

g - Browse to family
.P
This command switches to the family display; the family will be the
one that the current person belongs to as spouse or parent.
If there are more than one such family, LifeLines will ask you to
identify the proper one.

q - Return to main menu
.P
This command leaves the browsing mode and returns you to the main
menu.

ADD OPERATION
.P
If you choose the add operation at the main menu, LifeLines
displays the add menu:

.ne 6
  What do you want to add?
   p  Person - add new person to the database
   f  Family - create family record from one or two spouses
   c  Child - add a child to an existing family
   s  Spouse - add a spouse to an existing family
   q  Quit - return to the previous menu

The operations all work in a straightforward way.  LifeLines asks you
the necessary questions along the way, and always lets you quit the
operations at any time without changing the database.
.P
All operations provided by this menu are also available from
the browsing mode, and are nearly always easier to perform from there.

DELETE OPERATION
.P
If you choose the remove operation at the main menu, LifeLines
displays the remove menu:

.ne 5
  What do you want to delete?
   c  Child - remove a child from his/her family
   s  Spouse - remove a spouse from a family
   p  Person - remove a person completely
   q  Quit - return to the previous menu

These operations also work in a straightforward way.
LifeLines asks you the necessary questions along the way, and lets you
cancel at any time.
.P
You can also remove a child from his/her family, or remove a spouse/parent
from his/her family, from the browsing mode.
In both cases, only a relationship is removed, not a person.
On the other hand, the delete menu must be used if you want to completely
remove a person from the database;
this cannot be done from the browsing mode.
.P
Note that there is no special operation for removing a family record.
LifeLines silently removes any family record that has no parent
or child associated with it.

MISCELLANEOUS UTILITIES
.P
If you choose the miscellaneous utilities operation,
LifeLines displays the utilities menu:

.ne 9
  What utility do you want to perform?
   s  Save the database in a GEDCOM file
   r  Read in data from a GEDCOM file
   k  Find an individual's key value
   i  Identify a person from key value
   d  Show database statistics
   m  Show memory statistics
   e  Edit the abbreviation file
   q  Return to the previous menu

s - Save the database in a file
.P
This command lets you save a complete LifeLines database in a GEDCOM
format file.
You should regularly back up your database by using this command.
When you select this command, LifeLines asks you the name of the file
to hold the "archive" file.

r - Read in data from a GEDCOM file
.P
This command allows you restore a complete database from a GEDCOM
"archive" file.
When you select this command, LifeLines asks you for the name of the
file containing the GEDCOM data.
This command can also be used to import data from a GEDCOM file
to an existing database.
When LifeLines performs this command, it first reads the entire GEDCOM
file and checks it for validity.
If there are problems in the GEDCOM file, LifeLines describes them, and
does not add any records to the database.
If there are no problems, LifeLines adds all the person and family
records found in the file (if there other types of records they are
ignored).

k - Find an individual's key value
.P
This command retrieves the internal key value of a person.

i - Identify a person from key value
.P
This command identifies the person that has a particular internal key
value.

d - Show database statistics
.P
This command summarizes the contents of the current database.
It displays the name of and the number of persons and families
currently stored in database.

m - Show memory statistics
.P
This command is used by the author (me) for debugging; it is not
very useful otherwise.

e - Edit abbreviation file
.P
This command allows you to edit the place abbreviations file.
This file defines the abbreviations that are used by LifeLines when it
creates lists of persons for you to select from.
The file has the following format:

  Calif.@California
  Can.@Canada
  Conn.@Connecticut
  Eng.@England
  I. of M.@Isle of Man
  Mass.@Massachusetts
  N.S.@Nova Scotia
  Nfld.@Newfoundland
  R.I.@Rhode Island

Each line is an abbreviation, an @-sign, and the word abbreviated.
When LifeLines constructs lists of persons for you to select from, it
looks up the last component of certain PLAC lines in this file, and if
it finds that component, replaces it with its abbreviation.

q - Return to previous menu
.P
This command returns you to the main menu.

.ne 21
MERGING PERSONS AND MERGING FAMILIES
.P
LifeLines provides features for merging persons together and for
merging families together.
The person merging feature is accessed from the tandem person browse
mode, and the family merging feature is accessed from the tandem family
browse mode.
Merging is necessary when you discover that two or more person records,
or two or more family records, represent the same person or family,
respectively.
.P
Persons can be merged if they meet two criteria.
First, if both persons are parents/spouses in families, then they must
have the same sex.
Second, if they are both children, then they must be children in
the same family.
When two persons are merged, the combined person will become a
spouse/parent in exactly the same families that the two original persons
were spouses/parents in.
.P
Two families can be merged together if they meet two criteria.
First, if they both have a father/husband, then these persons must be
the same.
Second, if they both have a mother/wife, then these persons must be the
same.
It is okay for one or both families to be missing one or both
parents/spouses.
The merged family will have the same parents/spouses as the original
families, while the children of the merged family will be the
combined children from the original families.
.P
The list browse mode provides a convenient way to search for potential
persons to merge.
When two persons are identified in the same list for merging, mark one
of them and make the other one current.
Then use the 't' command to enter the tandem mode with the two
persons.
Then proceed with the merging.

.ne 2i
THE REPORT GENERATOR
.P
The report generator is a unique feature of LifeLines.
It lets you program reports in any style or layout.
You may generate files in troff, postscript, TeX, or any other
ASCII-based format, for further text processing and printing.
.P
The report generator is an entire programming subsystem.
Each report is described by a program written in the report generator
language; the programs are stored in files.
When you direct LifeLines to generate a report, it asks you for the
name of the program file, asks you where you want the output report
written, and then runs the program.
.P
For example, say you want LifeLines to generate an ahnentafel.
Such a report might look like:

.nf
.in +2
Ahnentafel Table for Thomas Trask WETMORE IV

1. Thomas Trask WETMORE IV
     b. 18 December 1949, New London, Connecticut
2. Thomas Trask WETMORE III
     b. 15 October 1925, New London, Connecticut
3. Joan Marie HANCOCK
     b. 6 June 1928, New London, Connecticut
4. Thomas Trask WETMORE Jr
     b. 5 May 1896, New London, Connecticut
     d. 8 November 1970, New London, Connecticut
5. Vivian Genevieve BROWN
     b. 5 April 1896, Mondovi, Wisconsin
6. Richard James HANCOCK
     b. 18 August 1904, New London, Connecticut
     d. 24 December 1976, Waterford, Connecticut
7. Muriel Armstrong SMITH
     b. 28 October 1905, New Haven, Connecticut
8. Thomas Trask WETMORE Sr
     b. 13 March 1866, St. Mary's Bay, Nova Scotia
     d. 17 February 1947, New London, Connecticut
9. Margaret Ellen KANEEN
     b. 27 October 1859, Liverpool, England
     d. 10 May 1900, New London, Connecticut
.in -2
.fi

Writing a LifeLines report program to generate this report is
straightforward.
Here is such a program:

.nf
proc main ()
{
      getindi(indi)
      list(ilist)
      list(alist)
      enqueue(ilist, indi)
      enqueue(alist, 1)
      while(indi, dequeue(ilist)) {
            set(ahnen, dequeue(alist))
            d(ahnen) ". " name(indi) nl()
            if (e, birth(indi)) { "    b. " long(e) nl() }
            if (e, death(indi)) { "    d. " long(e) nl() }
            if (par, father(indi)) {
                  enqueue(ilist, par)
                  enqueue(alist, mul(2,ahnen))
            }
            if (par,mother(indi)) {
                  enqueue(ilist, par)
                  enqueue(alist, add(1,mul(2,ahnen)))
            }
      }
}
.fi

Say this program is in a file named "ahnen".
When you choose the r option from the main menu, LifeLines asks:

.ne 2
  What is the name of the report program?
  enter file name:

You would enter "ahnen".
LifeLines then asks where the generated report should be written:

.ne 2
   What is the name of the output file?
   enter file name:

You enter a file name, say "my.ahnen."
LifeLines now reads the report program "ahnen," executes the program,
and writes the report output to "my.ahnen."
LifeLines will report on any syntax or run-time errors
found while trying to generate the report.
.P
A report program is made up of one or more procedures and functions; one
of the procedures must be named "main."
The main procedure is executed first; it may call other procedures,
functions and builtin functions.
In the example there is only one procedure.
.P
A procedure body is a sequence of expression items and statement items.
In the example program the first five items are:

  getindi(indi)
  list(ilist)
  list(alist)
  enqueue(ilist, indi)
  enqueue(alist, 1)

The first item calls the get-individual function, which causes LifeLines
to ask you to identify a person:

   Identify person for interpreted report
   enter name:

This sets variable "indi" to refer to the identified person.
The next two items declare the intention to use the lists
"ilist" and "alist".
Lists hold sequences of things; there are operations for putting
things on lists, taking things off, and iterating through the members.
In the example, "ilist" holds the list of ancestors, in ahnentafel
order, who have not yet been reported on, and "alist" holds their
ahnentafel numbers.
A one-to-one correspondence between the lists is maintained.
.P
The next two items call the "enqueue" function, adding the first
members to both lists.
The person identified by the "getindi" function is put on "ilist", and
the number one, the person's ahnentafel number, is put on "alist".
.P
The rest of the program is:

   while(indi, dequeue(ilist)) {
         set(ahnen, dequeue(alist))
          d(ahnen) ". " name(indi) nl()
          if (e, birth(indi)) { "    b. " long(e) nl() }
          if (e, death(indi)) { "    d. " long(e) nl() }
          if (par, father(indi)) {
                 enqueue(ilist, par)
                 enqueue(alist, mul(2,ahnen))
          }
          if (par, mother(indi)) {
                 enqueue(ilist, par)
                 enqueue(alist, add(1,mul(2,ahnen)))
          }
   }

This is a loop that removes persons and their
ahnentafel numbers from the two lists, and then prints their names
and birth and death information.
If the persons have parents in the database, the parents and their
ahnentafel numbers are then put at the ends of the lists.
.P
The loop is a "while" loop.
The line:

  while(indi, dequeue(ilist)) {

removes (via "dequeue") a person from "ilist", and assigns the person
to the variable "indi."
As long as there are persons on "ilist," another iteration of the loop
follows.
.P
The item:

  set(ahnen, dequeue(alist))

is an assignment expression.
The second argument to "set" is evaluated; its value is assigned
to the first argument, which must be a variable.
In this case the next number from "alist" is removed and
assigned to the variable "ahnen."
This is the ahnentafel number of the person just removed from
"ilist".
.P
The line:

  d(ahnen) ". " name(indi) nl()

is made up of four items.
The "d" function writes its argument to the report file as
a decimal number.
The ". " is a literal.
Literals are written to the output unchanged.
The "name" function writes out the default format of a person's name.
The "nl" function writes a newline to the report file.
.P
The next two lines:

  if(e, birth(indi)) { "    b. " long(e) nl() }
  if(e, death(indi)) { "    d. " long(e) nl() }

write out basic birth and death information about a person.
These lines are if-statements.
The second argument in the conditional is evaluated and assigned
to the first argument, which must be a variable.
The first if-statement calls the "birth" function, returning
the first birth event in a person's record.
If the event exists it is assigned to variable "e", and the body
(the items between the curly brackets) of the if-statement
is executed.
The body consists of three items:  a literal, and calls to
the "long" and "nl" functions.
The "long" function takes an event, and writes out the
values of the first DATE and PLAC lines in the event.
.P
Finally in the program is:

  if (par,father(indi)) {
          enqueue(ilist,par)
          enqueue(alist,mul(2,ahnen))
  }
  if (par,mother(indi)) {
          enqueue(ilist,par)
          enqueue(alist,add(1,mul(2,ahnen)))
  }

These lines add the father and mother of the current person, if
either or both are in the database, to "ilist."
They also compute and add the parents' ahnentafel numbers to "alist."

.ne 2i
REPORT GENERATION LANGUAGE SUMMARY
.P
A report program is made up of one or more procedures and functions.
A procedure has format:

    proc <name> ( <params> ) { <items> }

The <name> is the name of the procedure, <params> is an
optional list of parameters separated by commas, and
<items> is a list of items that makes up the body of the
procedure.
Report generation begins with the first item in procedure "main."
Procedures may be called by other procedures and functions.
When a procedure is called the items that make it up are executed.
.P
A function has format:

    func <name> ( <params> ) { <items> }

Functions may be called by procedures and functions.
When a function is called the items that make it up are executed.
A function differs from a procedure because it returns a value to the
procedure or function that called it.
Values are returned by the

	return ( <expr> )

item, which is described below.
.P
There are a number of item types.
The simplest is an expression, defined more fully below.
An expression item is evaluated, and if its value is non-null
(non-zero), it is assumed to be a string value, and written directly
to the output file.
If its value is zero, then the expression does not generate text to
the report file.
For example, the expression:

    name(indi)

evaluates the name of a person, and the name is written to the
report file.
On the other hand, the expression:

    set(n, nspouses(indi))

assigns the variable "n" the number of spouses that person "indi" has,
but the value of the "set" expression is null, so nothing is written to
the report file.
.P
The report language includes if statements, while statements
and procedure call statements, defined as:

  if ([<varb>,] <expr>) { <items> } [ else { <items> } ]

  while ([<varb>,] <expr>) { <items> }

  call <name> ( [<exprs>] )

An if statement is executed by first evaluating the conditional
expression.
If non-null, the items in the body are executed.
If the value is null, the items following the "else" keyword, if
any, are executed.
There are two forms of conditional expressions.
If the conditional is a single expression, it is simply
evaluated.
If the conditional is a variable followed by an expression,
the expression's value is also assigned to the variable.
.P
The while statement provides a looping mechanism.
The conditional is evaluated, and if non-null, the body of the
loop is executed.
After each iteration the expression is reevaluated; as long as it
remains non-null, the loop is repeated.
.P
The call statement provides procedure calls.
The <name> must match one of the procedures defined in the
report program.
Recursion is allowed.
When a call is executed, the values of its arguments are evaluated
and used to initialize the procedure's parameters.
The procedure is then executed.
When the procedure completes, execution resumes
with the first item after the call.
.P
In addition to these conventional statements, there are three
genealogical iteration statements:

  children (<expr>, <cvar>, <num>) { <items> }

  spouses (<expr>, <svar>, <fvar>, <num>) { <items> }

  families (<expr>, <fvar>, <svar>, <num>) { <items> }

The first loops through all children in a family.
The first argument must be a family expression.
During each iteration <cvar> is successively assigned to each
child in the family.
Argument <num> is iteratively assigned the numbers 1, 2, ...,
and so on.
These two variables may be used throughout the items in the loop
body.
This loop generates the names of each child in a family, preceded by
their order numbers as Roman numerals:

  children(fam, child, no) {
        roman(no) ". " name(child) nl()
  }

The value of "fam" must refer to a family;
"child" and "no" are local loop variables.
.P
In the spouses statement the first argument must be a person
expression.
During the iterations, <svar> is assigned to each of the
person's spouses, and <fvar> is assigned the corresponding
family; <num> indexes the spouses.
.P
In the families statement the first argument must also be a
person expression, and <fvar> and <svar> take on the value of each
family and associated spouse of the person in turn; the value of <svar>
is null if the corresponding family has no known second spouse.
.P
There are six other iteration statements:

  forindi (<indi>, <num>) { <items> }

  forfam (<fam>, <num>) { <items> }

  forindiset (<indiset>, <indi>, <val>, <num>) { <items> }

  forlist (<list>, <element>, <num>) { <items> }

  fornodes (<root>, <node>) { <items> }

  traverse (<root>, <node>, <lev>) { <items> }

.P
The forindi statement loops through every person in the database, one
after the other in ascending key order; <indi> refers to each person in
turn, and <num> is an integer that counts them.
.P
The forfam statement loops through every family in the database, one
after the other in ascending key order; <fam> refers to each family in
turn, and <num> is an integer that counts them.
.P
The forindiset statement loops through every person in an "indiset" data
structure.
An indiset is a set of persons that may possibly be sorted by name
or by key or by other values
(see the functions "indiset," "addtoset," "union," "intersect,"
"parentset," "childset," "spouseset," "ancestorset," "descendentset,"
"gengedcom," "namesort," "keysort" and "valuesort").
The expression <indiset> must evaluate to an indiset; <indi> is a loop
variable that iterates through each person in the set; <val> iterates
through the extra values that may be associated with each person in the
set; and <num> counts the loop iterations.
.P
The forlist statement loops through every element in a list data
structure.
A list is a sequence of data objects (see the functions "list," "empty,"
"enqueue," "dequeue," "push," "pop," "requeue," "setel" and "getel").
The expression <list> must evaluate to a list; <element> is a loop
variable that iterates through each list element; and <num> counts the
iterations.
.P
The fornodes statement loops through GEDCOM nodes in a person or
family record.
The first argument must be an expression that refers to a node in a
database record; <node> is a loop variable that iterates through the
GEDCOM nodes that are one level deeper than the original node.
.P
The traverse statement provides a general mechanism for traversing
entire or partial records.
The first argument must evaluate to a node in a database record;
<node> is a loop variable that iterates over every node under the <root>
node in a top down and left to right manner (think of the GEDCOM record
as a recursive parse tree of nodes); and <lev> is a loop variable set
to the level of <node>.
.P
There are four kinds of expressions:

    <literal>
    <integer>
    <variable>
    <identifier> (<exprs>)

A <literal> is any string enclosed in double quotes; its value is
itself.
An <integer> is any integer constant; its value is itself.
A <variable> is a named location that can be assigned different values
during program interpretation.
The value of a <variable> is the last value assigned to it.
An <identifier> followed by comma-separated list of expressions enclosed
in parentheses, is a call to a built-in function.

Built-in Functions
.P
There is a long list of built-in functions, and this list will probably
continue to grow for some time.
The list here represents only a snapshot in time.

Value Types
.P
In the summaries below each function is shown, along with its return type,
and with the types of its arguments.
These types are the following:

  ANY \(em this pseudo-type represents any type at all
  INT \(em integer
  BOOL \(em boolean
  STRING \(em text string
  LIST \(em arbitrary length list
  TABLE \(em keyed lookup table
  SET \(em arbitrary length person set
  VARB \(em not a type; indicates parameters that must be variables
  INDI \(em individual (person); reference to a GEDCOM INDI record
  FAM \(em family; a reference to a GEDCOM FAM record
  NODE \(em GEDCOM node; reference to a line in a GEDCOM record
  EVENT \(em event; reference to a structure of lines in a GEDCOM record
  VOID \(em pseudo-type that has no values

Arithmetic and Logic Functions
.P
These functions perform arithmetic and logic.
The "strcmp" function compares two strings and returns an integer that
is less than zero, equal to zero, or greater than zero, if
respectively, the first string is lexicographically less than, equal
to, or greater than the second string.

  INT add(INT,INT) \(em addition
  INT sub(INT,INT) \(em subtraction
  INT mul(INT,INT) \(em multiplication
  INT div(INT,INT) \(em division
  INT mod(INT,INT) \(em modulus
  INT neg(INT) \(em integer negation

  VOID incr(VARB) \(em increment variable by one
  VOID decr(VARB) \(em decrement variable by one

  BOOL and(BOOL,BOOL) \(em logical and
  BOOL or(BOOL,BOOL) \(em logical or
  BOOL not(BOOL) \(em logical not

  BOOL eq(ANY,ANY) \(em equality (not strings)
  BOOL ne(ANY,ANY) \(em non-equality
  BOOL lt(ANY,ANY) \(em less than
  BOOL gt(ANY,ANY) \(em greater than
  BOOL le(ANY,ANY) \(em less than or equal
  BOOL ge(ANY,ANY) \(em greater than or equal


  INT strcmp(STRING,STRING) \(em string compare

Individual Functions
.P
These functions take a person as an argument and return
information about him or her.
A few need explanation.
Function "pn" is a pronoun generator, useful when generating
English text; the second parameter selects
the type of pronoun:

  0 \(em He/She
  1 \(em he/she
  2 \(em His/Her
  3 \(em his/her
  4 \(em him/her

Function "fullname" generates names in many formats.
If the second parameter is TRUE the surname is shown in upper
case; otherwise the surname is as in the record.
If the third parameter is TRUE the parts of the name are shown in the
order as found in the record; otherwise the surname is given first,
followed by a comma, followed by the other name parts.
The fourth parameter specifies the maximum length field that can be
used to show the name; various conversions occur if it is necessary to
shorten the name to fit this length.
Function "key" returns the key value of a person or family; it there
is a second parameter and it is non-null, the leading 'I' or 'F' will
be stripped.

  EVENT birth(INDI) \(em first birth event of
  EVENT death(INDI) \(em first death event of
  EVENT baptism(INDI) \(em first baptism event of
  EVENT burial(INDI) \(em first burial event of
  INDI father(INDI) \(em father of
  INDI mother(INDI) \(em mother of
  INDI nextsib(INDI) \(em next (younger) sibling of
  INDI prevsib(INDI) \(em previous (older) sibling of
  STRING name(INDI) \(em default name of
  INT nspouses(INDI) \(em number of spouses of
  INT nfamilies(INDI) \(em number of families (as spouse/parent) of
  STRING sex(INDI) \(em sex of
  STRING title(INDI) \(em first title of
  STRING key(INDI|FAM [,BOOL]) \(em internal key of (works for family also)
  STRING pn(INDI,INT) \(em pronoun referring to
  STRING fullname(INDI,BOOL,BOOL,INT) \(em many name forms
  STRING surname(INDI) \(em surname of
  STRING givens(INDI) \(em given names of
  BOOL male(INDI) \(em male predicate
  BOOL female(INDI) \(em female predicate
  STRING trimname(INDI,INT) \(em trimmed name of
  NODE inode(INDI) \(em root GEDCOM node of
  FAM parents(INDI) \(em parents' family of
  STRING soundex(INDI) \(em SOUNDEX code of

Family Functions
.P
These functions take a family as an argument and return
information about it.

  EVENT marriage(FAM) \(em marriage event of
  INDI wife(FAM) \(em wife/mother of
  INDI husband(FAM) \(em husband/father of
  INT nchildren(FAM) \(em number of children in
  STRING key(FAM|INDI[,BOOL]) \(em internal key of (works for person also)
  NODE fnode(FAM) \(em root GEDCOM node of

List Functions
.P
These functions provide the list data structure.
A list must be declared with the "list" function before it is used.
Functions "enqueue," "dequeue" and "requeue" allow the list to be accessed
as a queue ("enqueue" adds to the back of the queue, and "requeue"
adds to the front); "push" and "pop" allow stack access; "empty" checks
whether the list is empty.
The functions "setel" and "getel" allow the list to be accessed as an
array; unassigned elements of arrays are assumed to be NULL.
The "forlist" statement (described above) can be used to iterate
through a list.

  VOID list(VARB) \(em declare a list
  VOID enqueue(VARB,ANY) \(em enqueue element on list
  ANY dequeue(VARB) \(em dequeue and return element from list
  VOID requeue(VARB,ANY) \(em requeue an element on list
  BOOL empty(VARB) \(em check if list is empty
  VOID push(VARB,ANY) \(em push element on list
  ANY pop(VARB) \(em pop and return element from list
  VOID setel(VARB,INT,ANY) \(em array element assignment
  ANY getel(VARB, INT) \(em array element selection

Table Functions
.P
LifeLines provides a general purpose table data structure.
A table must be declared with the "table" function before it is used.
The "insert" function adds a keyed object to the table (the second
parameter is the object's key; the third parameter the object); if
there is already an object in the table with the given key, the old
object is replaced with the new.
The "lookup" function retrieves the object with the given key (second
parameter); if there is no such object, null is returned.

  VOID table(VARB) \(em declare a table
  VOID insert(VARB,STRING,ANY) \(em insert entry in table
  ANY lookup(VARB,STRING) \(em lookup and return entry from table

GEDCOM Node Functions
.P
These functions take a GEDCOM node as a parameter and return values
associated with it.
They can be used with the fornodes and traverse iteration
statements to write general purpose information extraction routines.

  STRING tag(NODE) \(em tag of
  STRING value(NODE) \(em value of, if any
  STRING xref(NODE) \(em cross reference index of, if any
  NODE parent(NODE) \(em parent node of, if any
  NODE child(NODE) \(em first child of, if any
  NODE sibling(NODE) \(em next sibling of, if any

White Space Format Functions

  STRING nl() \(em newline character
  STRING sp() \(em space character
  STRING qt() \(em double quote character

Event and Date Functions
.P
These functions are used to extract information about events and write
it to the report file.
The last four functions are used to format dates in a variety of ways.
The functions "dayformat," "monthformat," and "dateformat" select
style options for formatting the day, month, and overall date structure;
"stddate" writes dates in the selected style.
The day formats are:

  0 \(em leave space before single digit days
  1 \(em use leading 0 before single digit days
  2 \(em no space or leading 0 before single digit days

The month formats are:

  0 \(em number with space before single digit months
  1 \(em number with leading zero before single digit months
  2 \(em number with no space or zero before single digit months
  3 \(em upper case abbreviation (eg, JAN, FEB)
  4 \(em capitalized abbreviation (eg, Jan, Feb)
  5 \(em upper case full word (eg, JANUARY, FEBRUARY)
  6 \(em capitalized full word (eg, January, February)

The overall date formats are:

  0 \(em da mo yr
  1 \(em mo da, yr
  2 \(em mo/da/yr
  3 \(em da/mo/yr
  4 \(em mo-da-yr
  5 \(em da-mo-yr
  6 \(em modayr
  7 \(em damoyr
  8 \(em yr mo da
  9 \(em yr/mo/da
 10 \(em yr-mo-da
 11 \(em yrmoda

  STRING date(EVENT) \(em date of; value of first DATE line
  STRING place(EVENT) \(em place of; value of first PLAC line
  STRING year(EVENT) \(em year of; first string of 4 digits from first DATE line
  STRING long(EVENT) \(em date and place of; values of first DATE and PLAC lines
  STRING short(EVENT) \(em date and place of; abbreviated form
  EVENT gettoday() \(em returns the "event" of the current date

  VOID dayformat(INT) \(em set day format for stddate calls
  VOID monthformat(INT) \(em set month format for stddate calls
  VOID dateformat(INT) \(em set date format for stddate calls
  STRING stddate(EVENT) \(em date of, in current format

Value Extraction Functions
.P
Value extraction functions are used to read the values of certain line
types and return those values in more convenient forms for
processing.
The "extractdate" function extracts date values from either an EVENT or
DATE line.
The first parameter must be a GEDCOM NODE; if its tag is DATE, the
date is extracted from the value of the NODE; if its tag is not DATE,
then the date is extracted from the first DATE line one level below
the node.
The remaining three parameters must be variables.
The first variable is assigned the integer value of the extracted
day.
The second variable is assigned the integer value of the extracted
month.
And the third variable is assigned the integer value of the extracted
year.
For example, the call to "extractdate(birth(i), da, mo, yr)" will
extract the day, month and year of the birth of person "i" and assign
these three values to the integer variables "da", "mo" and "yr".
.P
The "extractnames" function extracts name components from a NAME line.
Its first parameter must be either an INDI or a NAME line.
If it is a NAME line, the components are extracted from the value of
the line; if it is an INDI line, the components are extracted from the
value of the first NAME line in the person record.
The first parameter must be the node.
The second parameter must be a list that will hold the extracted
components.
The third parameter must be a variable; it is set to the number of
extracted components.
The fourth parameter must also be a variable; it is set to the index
(starting at one) of the surname component; the / characters are
removed from around the surname component.
.P
The "extractplaces" function extracts place components from a PLAC
line.
The first parameter must be a GEDCOM NODE; if its tag is PLAC, the
places are extracted from the value of the NODE; if its tag is not
PLAC, the places are extracted from the first PLAC line one level
below the node.
The second parameter must be a list that will hold the extracted
components.
The third parameter must be a variable; it is set to the number of
extracted components.
Place components are defined by the comma-separated portions of the
PLAC value; all leading and trailing white space is removed from the
components, while all internal white space is retained.
  
  VOID extractdate(NODE,VARB,VARB,VARB) \(em extract a date
  VOID extractnames(NODE,LIST,VARB,VARB) \(em extract a name
  VOID extractplaces(NODE,LIST,VARB) \(em extract a place

Assignment Function
.P
The assignment function is used to assign values to variables.
Note that the conditional expression used in both while and if
statements can also be used to assign a value to a variable.
The first argument must be a variable; the second argument can be any
expression.

  VOID set(VARB,ANY) \(em assignment operator

Global Function
.P
The "global" function gives a variable global scope.
Unlike all other built-in functions, this function must be "called"
from outside the scope of any procedure.
The variable can then be accessed from within any procedure.
This can be very useful when you need many procedures to access the
same data structure.

  VOID global(VARB) \(em give a variable global scope

User Interaction Functions
.P
These functions interact with the user to gather information required
by the rest of the program.
The "getindi," "getindiset," "getfam," "getint" and "getstr" functions
use a default prompt.
The "getindimsg," "genintmsg" and "getstrmsg" functions allow you to provide
a your own prompt message.

  VOID getindi(VARB) \(em identify person through user interface
  VOID getindiset(VARB) \(em identify set of persons via user interface
  VOID getindimsg(VARB,STRING) \(em identify person through user interface
  VOID getfam(VARB) \(em identify family through user interface
  VOID getint(VARB) \(em get integer through user interface
  VOID getintmsg(VARB,STRING) \(em get integer through user interface 
  VOID getstr(VARB) \(em get string through user interface
  VOID getstrmsg(VARB,STRING) \(em get string through user interface 

Number Format Functions
.P
The "d," "ord," "alpha," "roman" and "card" functions convert numbers
into strings.
The "strtoint" function converts a numeric string into an integer.
The function "atoi" is identical to "strtoint".

  STRING d(INT) \(em number as decimal string
  STRING card(INT) \(em number in cardinal form (one, two, three, ...)
  STRING alpha(INT) \(em convert number to Latin letter (a, b, c, ...)
  STRING roman(INT) \(em number in Roman numeral form (i, ii, iii, ...)
  STRING ord(INT) \(em number in ord form (first, second, ...)
  INT strtoint(STRING) \(em convert numeric string to integer
  INT atoi(STRING) \(em convert numeric string to integer

String Functions
.P
The "print" function prints a string to the standard output panel.
This can be used to provide information or feedback while reports are
being generated.
The "save" function makes a copy of the argument string and returns
it.
This function is required because most run-time functions that return
strings reuse the same static areas to hold those strings; if a string
is to be used repeatedly or long after it is returned from a function,
it should first be saved by using the "save" function.
The "substring" function returns a substring of the first argument
string.
The second and third parameters provide the character indices that
define the starting and ending characters within the string.
The indexes are relative one indexes.
The "substring" function reuses the same memory space to construct
substrings.
Therefore, if a substring must be retained for a long period of time,
it should be saved using the "strsave" or "save" function.
The "index" function returns the relative one index location of the
nth occurrence of a substring within a string.
The first parameter is the string; the second parameter is the
substring; and the third parameter specifies the occurrence number.
The "rjustify" function right justifies a string into a field of a
given length; if the string is longer than the field length the string
is truncated.

  VOID print(STRING) \(em print string to standard output window

  STRING lower(STRING) \(em convert to lower case
  STRING upper(STRING) \(em convert to upper case
  STRING capitalize(STRING) \(em capitalize first letter
  STRING trim(STRING,INT) \(em trim to length
  STRING rjustify(STRING,INT) \(em right justify in field

  STRING save(STRING) \(em save and return copy of string
  STRING strsave(STRING) \(em identical to the save functions
  STRING concat(STRING, STRING) \(em catenate two strings
  STRING strconcat(STRING, STRING) \(em catenate two strings
  INT strlen(STRING) \(em number of characters in string

  STRING substring(STRING, INT, INT) \(em substring function
  INT index(STRING, STRING, INT) \(em index function

  INDI indi(STRING) \(em returns person with given key value
  FAM fam(STRING) \(em returns family with given key value

Output Mode Functions
.P
Reports can be generated in two modes, line mode and page mode.
The "linemode" and "pagemode" functions switch back and forth
("linemode" is the default) between them.
When in line mode, the report is written as the program executes,
line by line.
When in page mode, however, output is buffered into pages which are
output only when the "pageout" function is called.
The page mode is useful for generating charts (eg, pedigree charts,
box charts) where it is convenient to compute the two-dimensional
location of output.
The "col" function can be used in both line and page mode; the "row"
and "pos" functions can only be used in the page mode.

  VOID linemode() \(em use line output mode
  VOID pagemode(INT,INT) \(em use page output mode with page size (row, col)
  VOID col(INT) \(em position to column in output
  VOID row(INT) \(em position to row in output
  VOID pos(INT, INT) \(em position to (row, col) coordinates in output
  VOID pageout() \(em output page buffer

File Functions
.P
The "newfile" function specifies the name of the report output
program.
Its first parameter is the name of the file; its second parameter is
an append flag \(en if its value is non-zero the report will be
appended to this file; if zero the report will overwrite the contents
of the file.
The "newfile" function can be called multiple times in order to
generate multiple reports from the same program execution.
Note: a program is not required to use the "newfile" function; if it
is not used then LifeLines will automatically ask you for the name of the
report output file.
The "outfile" function returns the name of the current report output
file.
The "copyfile" function is used to copy the contents of a file to the
output file; its argument must be a string whose value is the name of
a file; if the file name is not absolute nor relative, then the
LLPROGRAMS environment variable, if set, will be used to search for
the file; the file is opened and its contents copied to the output file.

  VOID newfile(STRING,BOOL) \(em direct report output to this file
  STRING outfile() \(em returns the name of the report output file
  VOID copyfile(STRING) \(em copy file contents to output file
  STRING database() \(em returns the name of the current database

Person Set Functions and GEDCOM Extraction
.P
The programming language supports a number of functions that
create and manipulate sets of persons and generate GEDCOM
files from sets of persons.
Variables that hold person sets must be declared with the "indiset"
operation.
A person can be added to a set with the "addtoset" function.
A person can be removed from a set with the "deletefromset" function.
The first argument must evaluate to a set, the second argument must
evaluate to a person, and the third argument can be any arbitrary
value.
A person can be removed from a set with the "deletefromset" function.
The first argument must evaluate to a set, the second argument must
evaluate to a person; if the third argument is TRUE all occurrences of
the person will be removed from the set, otherwise only the first
occurrence is removed.
The "ancestorset" function returns the person set which contains all
the ancestors of the persons in its argument set.
Similarly the "descendentset", "parentset", "childset", and
"spouseset" functions return the set of all descendents, parents,
children, and spouses, respectively, of their argument sets.
The "union", "intersect" and "difference" functions return the union,
intersection and difference, respectively, of two person sets.
The "namesort" and "keysort" functions are used to sort a set of
persons by name and by key value, respectively.
The "uniqueset" function first sorts a set by key value and then
removes all entries with duplicate keys; in this routine the input set
is modified and returned.
.P
Each person in a person set has a value associated with him or her.
When a person is added to a set with the "addtoset" function, this
value is explicitly assigned.
When new sets are created by the other functions, a number of rules
are used to associate values with persons as they are added to the new
sets.
For the "parentset", "childset" and "spouseset" functions the values are
copied from the first input set person that causes the new person to be
added to the set.
For the "union", "intersect" and "difference" functions, the values are
generally copied from the values in the first input set, except in the
case of "union", when persons are taken from the second set alone, in which
case the values come from there.
For "ancestorset" and "descendantset" the value is set to the
number of generations the new person is away from the person in the input
set that new person is related to.
If the new person is related to more than one person in the input set,
the value is always that of the nearest relationship; that is, the
value is as low as possible.
The "valuesort" function can be used to sort a person set by the
values of these auxiliary values.
The "gengedcom" function generates a GEDCOM format output, to the report
output file, of all the persons in the argument person set.
The GEDCOM output will contain a person record for all the persons in
the set, and all the family records that link the persons in the set
together.
In addition to these functions, the "forindiset" (described earlier)
looping construct can be used to iterate through each person in an indiset.

  VOID indiset (SET) \(em declare a set variable
  SET addtoset (SET, INDI, ANY) \(em add a person to a set
  SET deletefromset (SET, INDI, BOOL) \(em remove a person from set
  SET union (SET, SET) \(em return union of two sets
  SET intersect (SET, SET) \(em return intersection of two sets
  SET difference (SET, SET) \(em return difference of two sets
  SET parentset (SET) \(em return set of all parents 
  SET childset (SET) \(em return set of all children
  SET spouseset (SET) \(em return set of all spouses
  SET ancestorset (SET) \(em return set of all ancestors
  SET descendentset (SET) \(em return set of all descendents
  SET descendantset (SET) \(em same as "descendentset"; spelling variant
  SET uniqueset (SET) \(em key order and remove duplicates from a set
  VOID namesort (SET) \(em sort a set of persons by their names
  VOID keysort (SET) \(em sort a set of persons by their key values
  VOID valuesort (SET) \(em sort a set of persons by their auxiliary values
  VOID gengedcom (SET) \(em generate GEDCOM person and family records

Record Update Functions
.P
These functions allow you to modify an internal GEDCOM tree.
Function "createnode" creates a node from a tag and value string.
Function "addnode" adds a node to a node tree.
The first parameter is the new node; the second is the node in the
tree that is to be the parent of the new node; the third is the node
in the tree that is to be the previous sibling of the new node; this
parmaeter must be null if the new node is to be the first child of
the parent.
Function "deletenode" removes a GEDCOM node form a GEDCOM node tree.
Note: delete node has a memory leak.
Note: these functions only change the internal, GEDCOM tree form of
the records; they do not modify the database.
With the addition of "updatedatabase" (not yet available) it will be
possible to make permanent changes to the database from programs.

  NODE createnode (STRING, STRING) \(em create a GEDCOM node
  VOID addnode (NODE, NODE, NODE) \(em add a node to a GEDCOM tree
  VOID deletenode (NODE) \(em delete a node from a GEDCOM tree

Record Linking Functions
.P
These functions allow you to recognize node values that are cross
reference values, and to read the records the values refer to.
Function "reference" returns true if its string argument is a cross
reference value.
Function "dereference" returns the node tree of the record referred to
by its cross reference string argument.
Function "getrecord" is a synonym for "dereference."

  BOOLEAN reference (STRING) \(em determine if string is cross reference
  NODE dereference (STRING) \(em reads NODE tree for cross reference
  NODE getrecord (STRING) \(em same as dereference
