.TH AD 1
.SH NAME
ad \- query and maintain unstructured files of notes or a formal address database
.SH SYNOPSIS
.B ad
[-r, -e, -i, -l, -f, -fe, -fi] [-~opb] [-m {-, dbase_file}] [-D record_delimiter] [search_string_list]
.SH DESCRIPTION
.B Ad
carries out operations (query, editing, output, dialing) on 
database files, which may be structured or free form.
.PP
.B Ad 
can operate as a UNIX filter or in interactive mode. It 
accepts unstructured input, and thus can handle files of notes of 
varied type.  At its simplest, it is an overblown, optionally 
interactive 
.B grep.
At an intermediate level, 
.B ad
can treat nearly any text file, such as a collection of notes, as a 
database.
This can be searched and then displayed or edited, each paragraph a record.
Shell scripts or functions/aliases based on 
.B ad
can be used to mimic 
.B apropos
and 
.B whatis
and to query specific files of notes. 
At its most structured,
.B ad
will carry out 
operations (query, editing, output, dialing) on an address database.
In this case, each record consists of fields with name, address, telephone number and 
descriptive information, in fixed order.
.PP
Records and fields can be of any reasonable size.
They may be zero length.
The database searched can be changed by command-line option ("-m dbase_file").
.B Ad
can operate as a filter, with input from stdin ("-m -").
Records can be processed interactively ("-i" or "-fi").
They can be output continuously as raw information ("-r" or "-f")
or, for an address database,
as formatted information (under the default or the "-l" options).
Records are selected according to command-line search strings.
If there is more than one string, these are logically "and'd" in the search,
except if the "-o" option is present, the strings are logically "or'd".
.PP
Interactive mode ("-i" and "-fi") offers 
additional menu-selectable options.
The search strings may be changed.
The record pointer can be 
moved backward or forward by a specified number 
of records, independently of the search-string-based selection process.
There is automatic dialing with the address database.
Editing (from the interactive mode menu or under the
"-e" and "-fe" command-line options) is by forking a 
.B vi
process, which some may view as a feature.
Under 
.B vi 
there are "map'd" editing macros, which execute 
.B awk 
and
.B sed
scripts.
Editing a large database is slow.
It appears to be better to 
add new records into a small, ancillary database, 
and to modify old records by deleting 
from the main database and adding the altered record to an ancillary file. 
.PP
As noted,
.B ad
can operate either with free-from data files, or with
files carefully structured in the  order of the information fields.
The "address database" described below is a structured database.
.SS "COMMAND LINE OPTIONS"
Option syntax is as required for parsing by getopt(3C).
.PP
\fBOutput and Display:\fP
.TP 5
(\fBdefault\fP) 	summary display for address database
Write formatted one-line summary of selected
address database records to stdout.
.TP 5
\fB-l\fP 		full display for address database
Write formatted full display of all fields of selected 
address database records to stdout.
.TP 5
\fB-f\fP 		display for free form file
Selected records are passed through to stdout, without change,
except an added newline separating records.
.TP 5
\fB-i\fP		interactive mode for address database
Enter interactive mode, with full display
of the records selected;
output sent to stderr, unless write 
to stdout was chosen from the interactive menu.
.TP 5
\fB-fi\fP		interactive mode for free form file
As for the address database.
.TP 5
\fB-e\fP 		edit address database
Enter interactive editor, with "cursor"
pointing at selected record of the address database;
output sent to stderr.
.TP 5
\fB\&-fe\fP 		edit free form file
Enter \fBvi\fP directly, with cursor pointing
at selected record of the free-form file.
.TP 5
\fB-r\fP 		raw output selected from any type of input
Selected lines (records for the address database) 
are passed through to stdout.
There is no formatting, so "\fBad\fP -r" works like
.B grep.
.PP
\fBSearch Modification:\fP
.TP 5
\fB-m dbase_file\fP   input from "dbase_file"
"dbase_file" can be a file list, of either all free form files or
all address database files.
The file list can be  given either as a string 
enclosed in quotes with white
space separators or an unquoted string with colon separators.
"-m -" implies input from "stdin".
The default database list is a set of files, "ADRLIB/addrunix[.{p,b}]" and 
"ADRLIB/ad1234567890", 
comprised of structured address database records.
.TP 5
\fB\&-D record_delim\fP		record delimiter for free form file
The default is an empty line ("\\n\\n").
Any regular expression can be substituted.
The test for the match of text to delimiter
is made after each newline,
so record breaks are at newlines even if the delimiter does not end with "\\n".
.TP 5
\fB-p\fP  or  \fB-b\fP	select database section
Search the p=person or b=business address database only.
.TP 5
\fB-o\fP              switch to logical "or" of search strings
The default search is a logical "and'ing" of the command-line search strings.
.TP 5
\fB-~\fP              include deleted records
Deleted records are marked by a "~" inserted as the first character.
.PP
\fBSearch Strings:\fP
.TP 5
	        \fB[field{]string\fP
Search strings are RE"s and are logically "and'd" ("or'd" with -o option).
The optional prefix terminated with "{" restricts search to an address
database field.
The field prefix may be a number or a mnemonic (1=title to 14=flag).
.SS "SAMPLE USAGE - ADDRESS DATABASE"
Enter interactive mode ("-i"), search for the record(s)
matching all three words of the search string, 
display each match in full, formatted, 
with a menu of possible actions (e.g., dial
the telephone number, edit the record, search for the next match, etc):
.IP "" 5
\fBad\fP -i eric rup calif
.PP
Send the raw database record(s), found by search of the database, to stdout for
picking up by a pipe or a file or the display:
.IP "" 5
\fBad\fP -r eric rup calif
.PP
Send the full formatted database record(s), 
all information fields, found by the search, to stdout:
.IP "" 5
\fBad\fP -l eric rup calif
.PP
Send a one-line summary of the record(s) 
(title, first and last names and telephone number), to stdout:
.IP "" 5
\fBad\fP eric rup calif
.SS "SAMPLE USAGE - FREE FORM FILES"
Treat the file "README" as a database, in which empty lines are
taken as record delimiters.
To extract all records with the word "Install":
.IP "" 5
\fBad\fP -m README -f Install
.PP
A free-form database ("addrtest.free") was created 
from a structured address database by changing the
record delimiter to "%" ("\\n" to "\\n%\\n"),
putting each field on a separate line( ":" to "\\n"), 
and deleting all empty lines (fields).
To extract records with the words "micro" and "computer":
.IP "" 5
\fBad\fP -m addrtest.free -D% -f micro computer
.PP 
Something trivial - use of 
.B ad 
to 
.B grep 
a set of files,
e.g., to find lines with "FREE" in the source code for 
.B ad:
.IP "" 5
\fBcat\fP *.[ch] | \fBad\fP -m - -f -D. FREE
.PP
The output is nearly equivalent (the difference is 
newline record separators are added above) to the simpler:
.IP "" 5
\fBcat\fP *.[ch] | \fBad\fP -m - -r FREE
.PP
The file "/usr/man/whatis", constructed from the one-line
descriptions under man page "NAME" headings,
can be searched by 
.B ad
so as to mimic
.B apropos
and 
.B
whatis,
by use of the "undocumented" options "-w" and "-v".
These produce an appropriate search of the "whatis" file (i.e., the
"-w" option looks only at the line up to the hyphen separator)
and generate a nicely formatted output.  Shell scripts that do
an equivalent search and formatting run more slowly.
Shell aliases are convenient here:
.IP "" 5
\fBwhatis\fP='\fBad\fP -w'
.IP "" 5
\fBapropos\fP='\fBad\fP -vo'
.PP
A companion program,
.B note,
prepends dated lines of input to user selectable files in the
directory "/usr/home/memos".  Blocks of input are separated by
empty lines.
These can be conveniently queried
by wrapping 
.B ad 
in a shell script or shell function:
.in +5
#\fBquery\fP \- search [interactively] a file in $HOME/memos
.br
#usage:	\fBquery\fP memos_file [-i] search_strings
.br
\fBquery\fP() {
.br
FILE=$HOME/memos/$1
.br
shift
.br
\fBad\fP -f -m $FILE $*
.br
}
.in
.SS "MENU FOR INTERACTIVE MODE"
Interactive mode is entered under the command-line option "-i" for the
address database or "-fi" for a free-form file.  Interactive operation
is nearly identical for address database and free-form files.
The differences are the dial option
is only for the address database, and the edit option puts the user
directly into 
.B vi
for a free-form file 
or into the edit mode, with the edit menu, for the address database.
.PP
The following options are available after search of a database
has located a record.
.PP
dial displayed telno (\fBy\fP)?
.PP
enter a "number" to dial (\fB#number\fP)?
.PP
edit record (\fBe\fP)?
.PP
copy display to stdout (\fBp\fP)?
.PP
new search "string" (\fB$string\fP)?
.PP
forward or back by "n" records ([\fB-\fP]\fBn\fP)?
.PP
escape to shell (\fB!\fP)?
.PP
refresh (\fBr\fP)?
.PP
quit (\fBq\fP)?
.PP
else continue search.........
.SS "MENU FOR INTERACTIVE EDIT MODE - ADDRESS DATABASE"
Edit mode for an address database is entered with
the command-line option "-e" or from interactive mode with the
response "e".  The edit menu is not used with a free-form file, 
for which the "-e" 
option or the "e" response immediately loads and enters the 
.B vi
editor.
There are two ways to edit an address database.  
.PP
(\fBA\fP) An existing database
is edited by use of a scratch file that is a copy of the database.
The scratch file is created, if one does not already exist.
"ADRLIB/addrunix.b.scr" would be the scratch file for "ADRLIB/addrunix.b".
The scratch file stays in place in ADRLIB until the main database is
remade, i.e., until the main database is replaced by a merge of
the scratch file and any appropriate ancillary files.
Thus subsequent editing sessions add changes to the scratch file.
New records MUST NOT be added to the scratch file, because this would
destroy the one-to-one correspondence between scratch file and main file
records.
Editing of the scratch file is by forking a 
.B vi
process, in which the editor is loaded with the scratch file
and entered at the position of the record selected.
.PP
(\fBB\fP) Small ancillary address databases are created to contain new records.
The mechanism for doing this under the edit option is to create
a temporary "PULL" file ("ADRLIB/adpullfile").
As many records
as wished can be appended to the "PULL" file,
by selection from the interactive 
display of the address database records,
by reading from some other source,
or by entry as fresh information.
Editing is by forking a
.B vi
process, in which the editor is loaded with the "PULL" file.
The "PULL" file will remain in ADRLIB until it is destroyed or, more
likely, converted to an "ancillary" file, part of the address database.
This conversion, which can be done under the edit mode, is simply a
.B mv
of the file "ADRLIB/adpullfile" to "ADRLIB/admmddHHMMSS".
Files named like the later are automatically searched by
.B ad
as part of its default database.
Note that it is often easier to change a record of the main database 
by marking the record for deletion, pulling a copy of the record into
the "PULL" file, editing it there, and then whenever appropriate
installing the "PULL" file as an ancillary database file.
.PP
The following options are available in edit mode
after search of a the address database
has located a record.
.B Sed
and
.B awk
are run as part of most of the editing operations.
.TP 5
edit FULL file(\fBf\fP)
Edit a copy (the scratch file) of a main
address database file.
This is done by creating the copy if it does not exist, 
then loading the scratch file into and entering the
.B vi
editor, in a child process.
The editor cursor is set at the start of the current record.
Execution of the 
.B ad
process continues when editing terminates.
.TP 5
view change(\fBv\fP)
Look at the change that has been made in the current record
in the scratch file.
.TP 5
date(\fBd\fP)
Add a new penultimate field to the copy of the current record 
in the scratch file, 
with today's date in the format "yymmdd".  
This can also be done by use of a macro when in the 
.B vi
editor.
.TP 5
undate(\fBu\fP)
Remove a date field, if present.
.TP 5
delete(\fB~\fP) 
Mark the current record for deletion, 
by inserting a "~" as the first character in the scratch file copy.
.TP 5
undelete(\fB^\fP)
Remove the delete mark.
.TP 5
append to PULL file(\fB1\fP)
Append the displayed record to the "PULL" file.  Any number of records
may be appended to the "PULL" file.
.TP 5
edit PULL file(\fB2\fP)
Edit the "PULL" file, by loading it into the 
.B vi
editor and entering the editor, in a child process.
.TP 5
install PULL file(\fB3\fP)
Convert the "PULL" file into an address database ancillary file,
by renaming it.
.TP 5
escape to shell(\fB!\fP)
.TP 5
quit(\fBq\fP)
.TP 5
refresh display(\fBr\fP)
.TP 5
any other key = continue.....
.SS "STRUCTURED ADDRESS DATABASE"
Records are single line (delimited 
by "\\n"), with field separator ":". Fields, and thus records, are 
variable size, limited by the buffer sizes of system text handlers such 
as 
.B vi 
and 
.B awk
and by the (reconfigurable) size of the record
buffer of 
.B ad.
Fields may be zero length.  
No upper limit is set on the 
number of fields per record. 
A minimum number of fields (14) must be present in a record; additional fields 
are treated as comments. 
Formatting an address database record for display
consists of parsing on the field separators and 
output of the fields according to a pattern, i.e., what the author thinks 
is a nice display of name, number, address, and other information. 
.PP
Records can be processed 
interactively ("-i" command-line option) 
or can be output continuously, as formatted or raw 
information. 
Records are 
selected according to search strings, given as command line options or 
given by the operator in interactive mode.
If there 
is more than one string, these can be either logically "and'd" or "or'd" 
in the search.  
Interactive operation allows movement within the file by a 
specified number of records in either direction.
Editing is builtin, through an interface with \fBvi\fP, executed
from the edit mode menu, reached under the "-e" command-line option or
from the interactive mode menu.
Dialing is builtin, through an interface with \fBhayesdial\fP, executed
from the interactive mode menu.
.PP
As its default, 
.B ad
expects to find two main database files: 
"addrunix.b" and "addrunix.p",
the business and person sections of the database.
If
.B ad
does not find the two sections (".b" and ".p"), it looks for a single
main database file, "addrunix".
.B Ad
also looks for a set of up to 18 or 19
ancillary files, which store entries added since the last remake of the
address database.
The ancillary file names must be "ad" followed by 10 digits,
any digits you like, but different from those for other files 
(as a suggestion, the date and time, given as "mmddHHMMSS";
this is the default naming under edit mode).  
.SS "FREE-FORM FILES"
Records are multiline, delimited by any string that can be matched
by a regular expression.
The delimiter regular expression is by default "\\n\\n", an empty line; 
it can be reset by command-line option.  
Records are displayed as they are in the input 
file, except broken at the end of each line that has the record delimiter, i.e., 
there is no formatting except for insertion of newlines into the output at
the end of each record displayed.
Otherwise 
.B ad
functions for a free-form file as it does for a structured database, 
except: 
there is no automatic dialing with the response "y" from the interactive menu
(the "#number" response works regardless of file type);
and the "-e" command-line option and "e" interactive response
put the user directly into 
.B vi, 
rather than into edit mode.
.PP
Why go to the trouble of working with a structured database?
Processing is faster, and manipulation by the standard 
line-oriented UNIX text 
handling routines is simpler.  The cost is, for data entry and record 
editing, the time and effort of transforming between, on the one hand, 
a pretty unreadable single line with many fields,
and on the other hand, a display with
mnemonic identifiers and 
one field per line.  Editor macros make this 
transformation not too annoying.
.SS "RECORD FIELDS - ADDRESS DATABASE ONLY"
The fields of each record, with identifying 
number and mnemonic,  are the following:
.in +5
1 \fBtitle\fP         mr              
.br
2 \fBfirst\fP         eric            
.br
3 \fBlast\fP          rupley          
.br
4 \fBarea code\fP     619             
.br
5 \fBlocal telno\fP   459-7455        
.br
6 \fBaddr1\fP         7528 cuvier street
.br
7 \fBaddr2\fP         apt 8            
.br
8 \fBaddr3\fP                         
.br
9 \fBcity\fP          la jolla        
.br
10 \fBstate\fP        california      
.br
11 \fBzip\fP          92037           
.br
12 \fBcode\fP         p=family son univ
.br
13 \fBcomment\fP
.br
14 \fBflag\fP
.in
.PP
The example above is for a record of the person section of an address database.
Fields may be empty, but the field delimiters must be present, to maintain
the field count.
More than one "comment" field may be present (i.e., there may be more
than 14 fields).
Thus the database can be used to store and retrieve free-form
descriptive information in addition to address and telephone number.
Maximum record size is set by the system commands used to build and edit the
database, such as 
.B awk 
and 
.B vi, 
which have limits on line length.
The buffer size in 
.B ad
is easily reconfigurable.
.PP
The "code" field can be constructed for use in extracting records of
businesses or persons by category (e.g., in the above example, the
"p=" denotes a record of the person database section, and "family",
"son", and "univ" are increasingly specific identifiers of Eric).
If the "code" field is used as above, some thought should go into
selection of the categories.
For the business section, it has been helpful to make the "last"
field a classifier (e.g., "bank") 
that is also part of the code field, and to make the "first" field the
name of the business (e.g., "valley national").
.PP
If such categories are used, construction of the "code" 
and "last" fields
for businesses can be the most difficult part of data entry.
The files adhlp.{pcode, bcode, blast} have sample entries.
The file adhlp.code has a half-screen of prompts for the "code" entry,
and adhlp.category has more such information.
.SS "DATA ENTRY AND EDITING WITH VI - ADDRESS DATABASE ONLY"
The ".exrc" file for 
.B vi 
in ADRLIB has several macros mapped to keys:
.in +5
:map \fBv\fP 	ujg
.br
:map \fBV\fP 	ukg
.br
:map \fBK\fP 	/%^V^M
.br
:map \fB^O\fP 	mb
.br
:map \fB^A\fP 	K^O?%^V^M
.br
:map \fBg\fP 	!!adrecform^V^M
.br
:map \fBq\fP 	^A!'badrecrev^V^M
.br
:map \fB=\fP 	!!addate^V^M
.in
The macros most often used are:
.in +5
\fBg\fP		convert raw record to editable format
.br
\fBq\fP		unformat back to raw record
.br
\fB=\fP		insert current date as penultimate field
.in
.PP
Thus, to create a new record:
.sp
\fBcd\fP ADRLIB
.sp
\fBvi\fP scr
.br
:map       (to be sure that the rc file was read)
.br
:r adtemplate        (bring in a formatted template)
.br
(Alternatively, to get the template, open a new line, 
and with the cursor on it, in command mode, type "g".)
.br
(enter data, with one or more spaces between number-mnemonic and data;
each line must start with a new number-mnemonic;
add additional lines (fields) with "comment" as mnemonic starting them)
.br
\fBq\fP        (to unformat back to the raw record)
.br
\fB=\fP        (to enter date in next-to-last field)
.br
:r adtemplate
.br
(repeat above, until done with new entries)
.br
(if you want to edit an entry, move cursor to that line of file, then)
.br
\fBg\fP         (to convert raw record to editable format)
.br
(edit)
.br
\fBq\fP         (when done, unformat back to raw record)
.br
(note-- there should be only one formatted record in the file at one time)
.br
(when done with entries and editing)
.br
:w              (save the file)
.br
:q              (quit the editor)
.sp
\fBmv\fP scr ad0000000001         (create first ancillary file of new entries)
.PP
Editing an existing record is not substantially different from creating a
new record. 
The 
.B vi 
editor can be entered with the cursor on the record to be modified,
by selection of one of several choices offered by the editing menu, 
which is reached
from an interactive session started with the "-i" or "-e" command line options.

.SH FILES
Text files, including the address database, are found in ADRLIB = 
/usr/local/lib/address; change in ADRLIB
is by modification of the source code.
.sp
\fBaddrunix.b\fP	(default business database)
.br
\fBaddrunix.p\fP	(default person database)
.br
\fBadmmddHHMMSS\fP	(ancillary databases for recent entries)
.br
\fB\&.exrc\fP		(vi configuration file, with editing macros)
.br
\fBadtemplate\fP	(vi-usable template for record entry)
.br
\fBaddrunix.[bp].scr\fP	(edited database files)
.sp
shell scripts, which should be found somewhere on the PATH:
.br
\fBaddate, adrecform, adrecrev, adfreeform, adfreerev\fP
.sp
shell scripts in ./adscripts.misc, useful in maintining database and help files:
.br
\fBaddrunix.make\fP	(remake the address database)
.br
\fBadhlp.make\fP	(remake the address database help files)
.sp
dialer interface for a voice line, also on the PATH:
.br
.B hayesdial
.sp
doc files (in /usr/local/lib/address):
.br
.B adhlp.pcode,
.B adhlp.bcode,
.B adhlp.blast,
.B adhlp.code,
.B adhlp.category,
.B adhlp.edit
.SH "SEE ALSO"
\fBhayesdial(1), note(1), getopt(3C), regex(3X)\fP
.SH AUTHOR
John A. Rupley, 30 Calle Belleza, Tucson, AZ 85716
.br
{ihnp4, hao!noao}!arizona!rupley!local
.SH "BUGS AND CAVEATS"
There is no decent description of how to create and edit a
database, other than what you have here.
One hopes that the menus of
.B ad
are descriptive enough to lead the user properly.
.PP
If you elect to use the address 
database, then, because its structure is wired into the source code, 
you have 
to be happy with what the author likes, 
or be willing to hack the most unpleasant 
part of the code. 
.PP
The search is case sensitive, so for convenience, you may want to have all
entries lower case in an address database.
.PP
.B Hayesdial
is a companion program to
.B ad
and is not part of the standard SysV distribution.
.PP
.B Ad
is configured for a maximum of 20 database files, including the one
or two main files and all ancillary files.
.PP
Search is by brute force, so 
.B ad
is not recommended for a database of more than about 250,000 characters.
.PP
The code was written under SysV rel2 (Microport SysV/AT), and 
it should run in a generic SysV environment.  Possible porting problems 
- use of 
.B regex(), 
.B regcmp(), 
.B ftw() 
and 
.B optarg().
