\documentstyle[twoside,11pt]{article}
\pagestyle{headings}
\frenchspacing

\hyphenation{data-base}

\newcommand{\RET}{{\sc return}}
\newcommand{\TAB}{{\sc tab}}
\newcommand{\KEYUP}{$\Uparrow$}
\newcommand{\KEYDOWN}{$\Downarrow$}
\newcommand{\KEYLEFT}{$\Leftarrow$}
\newcommand{\KEYRIGHT}{$\Rightarrow$}

\author{Henk P. Penning \\ Computer Science Department, Utrecht University}
\title{Jinx}
\setcounter{tocdepth}{1}

\begin{document}

\maketitle

\tableofcontents

\section{Introduction}

{\em Jinx\/} is an interactive tool for manipulating simple databases.

A Jinx-database consists of an arbitrary number of records.
A record consists of fields.
A field may contain arbitrary {\sc ascii} printable data (no newlines or tabs).
All records in a single database have the same number of fields.
A database may therefore be viewed as a row of columns.
Associated with each column is a unique name (the fieldname).
There is no limit on the number of columns in a Jinx-database.
In a picture:
\begin{quote}\small
\begin{tabular}{l|c||c||c|c|c|}
\multicolumn{1}{c}{}           &
\multicolumn{1}{c}{column 1}   &
\multicolumn{1}{c}{column 2}   &
\multicolumn{1}{c}{column 3}   &
\multicolumn{1}{c}{}           &
\multicolumn{1}{c}{column $n$} \\
\multicolumn{1}{c}{}           &
\multicolumn{1}{c}{\em name 1} &
\multicolumn{1}{c}{\em name 2} &
\multicolumn{1}{c}{\em name 3} &
\multicolumn{1}{c}{}           &
\multicolumn{1}{c}{\em name n} \\
\cline{2-2} \cline{3-3} \cline{4-4} \cline{5-5} \cline{6-6}
record 1     & field 1 & field 2 & field 3 &        & field $n$ \\
record 2     & field 1 & field 2 & field 3 & \ldots & field $n$ \\
record 3     & field 1 & field 2 & field 3 &        & field $n$ \\ 
\ldots       & \ldots  & \ldots  & \ldots  & \ldots & \ldots    \\
record $k-2$ & field 1 & field 2 & field 3 &        & field $n$ \\
record $k-1$ & field 1 & field 2 & field 3 & \ldots & field $n$ \\
record $k$   & field 1 & field 2 & field 3 &        & field $n$ \\
\cline{2-2} \cline{3-3} \cline{4-4} \cline{5-5} \cline{6-6}
\end{tabular}
\end{quote}
Associated with each column is a regular expression which
is used as a constraint on the data that may be entered in the column.
Users can override constraints when entering or modifying data.

With Jinx you can manipulate at most one database at a time.
This database is called the {\em current\/} database.
Jinx enables the user to
\begin{itemize}
\item define a new database by adding fields to an existing or empty database.
\item open a database on disk to make that database the current one.
  The current database is a copy of the database on disk.
\item look at the raw data in the current database and move around in it
  by specifying a search pattern, setting a record number or
  paging back and forth.
\item inspect the current database at record-level.
  Records can be modified, added, copied and deleted.
  You can move around by searching for a specified pattern in the data etc.
\item create a new database by selecting certain columns from the
  current database.
  This is called {\em projection\/}.
\item create a new database by selecting records from the current database
  by specifying regular expressions for one or more fields.
  Any record with a field matching the given expression for that field is
  selected.
  This is called {\em extraction\/}.
\item create a new database by joining the current database with
  another database.
\item sort the current database.
\item copy records from another database.
\item check the uniqueness of entire records or the combination of one
  or more fields.
\item compute new values by specifying a Perl expression for one or more
  fields.
\item write the current database to disk.
  This is called {\em saving\/} the database.
\end{itemize}
When the user creates a new database by projection, extraction etc,
the new database becomes the current database.

Jinx marks the current database as {\em modified\/} or {\em not modified\/}.
A database is only marked {\em not modified\/} if it is an exact copy
of a database on disk.
After opening a database or saving one, the current database
is marked {\em not modified\/}.
Newly created databases are all marked {\em modified\/} initially.
When the current database is marked {\em modified\/} and the user
requests an action (like quiting Jinx, joining, projecting) that will
scratch the current database, Jinx will ask permission first.

When on disk, a Jinx-database consists of two files:
{\em name\/\tt.des} containing the descriptors and
{\em name\/\tt.dat} containing the data
(see section~\ref{implementation} for a description of their contents).
Jinx uses {\em name\/} to identify a database.
When opening a database a name has to be specified.
That name becomes the name associated with the current database.
Newly created databases are nameless.
Changing the descriptor (fieldnames and/or patterns) will make
the current database nameless.
The user must specify a name when a nameless database is to be saved.
That name becomes the name associated with the current database.
\\
You can use Jinx by typing:
\begin{quote}
\begin{tabular}{ll}
     & {\tt jinx}                       [ {\em name1 name2} $\ldots$ ] \\
or   & {\tt jinx -L}      {\em logfile} [ {\em name1 name2} $\ldots$ ] \\
or   & {\tt jinx -L}{\em level logfile} [ {\em name1 name2} $\ldots$ ] \\
or   & {\tt jinx -D} \\
or   & {\tt jinx -v}
\end{tabular}
\end{quote}
If a namelist is given, Jinx tries to open database {\em name1\/}.
The other names are are presented as defaults
when the opening of another database is requested.
If no namelist is given, Jinx just starts up without a current database.
With the L-option information is logged to the specified logfile.
By default, Jinx will log activities like opening and saving of databases.
Loglevel 1 or 2 are only there for debugging purposes and
will log many activities related to the presentation.
\\
The D-option will make Jinx dump core for undump-purposes.
The v-option will show version and copyright information.

When in Jinx, you usually see the following things on the screen.
At the top is information about the current database.
At the bottom of the screen are a menu, the status line and a command line.
The rest of the screen is used for presenting info in the database.
The amount of data shown depends on the size of the screen.

\section{Operations}

Jinx is menu driven.
Commands in menus are single characters (key strokes).
If the menu shows the entry {\tt ex)it},
it means you will have to type `{\tt x}'
when you want to {\em exit\/}.
If the menu shows the entry {\tt RET=foo},
you will have to type \RET{}
when you want to {\em foo\/}.
If the menu shows the entry {\tt TAB=p)arty},
typing \TAB{} or `{\tt p}' will make Jinx {\em party\/}.

Jinx always presents you with a default command.
By typing \RET{} you choose the default.
Instead of the commands \KEYLEFT{}, \KEYDOWN, \KEYUP{}, \KEYRIGHT,
you can use the {\tt hjkl}-commands.

Typing `{\tt ?}' to a command prompt, places you in help-mode.
In help-mode, you can get one line of text explaining some command
by typing in the command.
You exit help-mode by typing \RET{} or space.
In general, by typing \TAB{} you leave the current menu
with the least damage done.
Use it to back out of places where you don't want to be.

When you need to enter or modify a string, Jinx places you in edit-mode.
The cursor can be moved by \KEYLEFT{} and \KEYRIGHT.
Typing in the `kill' character (as defined by {\em stty\/}),
will delete the `character under the cursor'.
Typing in the `erase' character will delete the `character before the cursor'.
Other characters will be inserted except that
\RET, \TAB, \KEYUP{} and \KEYDOWN{} will make you leave edit-mode.
When you type `erase' in the first position of the string,
the string is swapped with an (initially empty) backup string.
Sometimes when you are requested to enter some string,
a default is presented.
You can discard the default by typing `erase' and then type in your own stuff.
Finish by typing \RET.
Any string you edit can be as long as you want.
When the length of the string exceeds the space reserved on the screen
for editing the string, the string will scroll in a peculiar manner.
Try it by opening a database with a loooong name.

\subsection{The meta-menu}\label{meta-menu}

After startup, Jinx presents the meta-menu.
It mainly contains commands which operate on a database as a whole
like opening, joining, sorting etc.
If there is a database current, the data part of the screen will show
the raw data in the database on a record per line basis.
The data is there to give a global overview.
When you have `long' records that don't fit on the screen,
you can move the view on the data right (left) by typing
\KEYRIGHT{} (\KEYLEFT).

You can page back- and forward through the data with the commands
{\em prev\/} and {\em next\/}.
The current record is indicated by a `{\tt >}' in the first column.
Move to the next (previous) record with \KEYDOWN{} (\KEYUP).

\subsubsection{goto}\label{goto}

Records in the database are numbered from 1 to whatever it takes.
The {\em goto\/} command asks for a record number and makes it the current record.
You can use $+N$ and $-N$ to indicate a number relative
to the number of the current record.
Finish entering the number with \RET.
With \KEYUP{} and \KEYDOWN{} you can step through numbers entered previously.
With \TAB{} you can indicate that you don't want to {\em goto\/} after all.

\subsubsection{search}

The {\em search\/} command asks for a search pattern and matches
records starting with the record following the current record.
If no following record matches, preceeding records are tried starting with
the first record.
If a record matches the pattern, it is made the current record.
Finish entering the pattern with \RET.
With \KEYUP{} and \KEYDOWN{} you can step through patterns entered previously.
With \TAB{} you can indicate that you don't want to {\em search\/} after all.

\subsubsection{re-search}

The {\em re-search\/} command repeats the last search command.

\subsubsection{inspect}

With {\em inspect\/} you enter the main-menu which is described in detail
in section \ref{main-menu}.
In the main-menu the database is shown on record-by-record basis.
In it are commands to update, copy, add, and delete records.

\subsubsection{Descr}

With {\em Descr\/} you enter the descriptor-menu which is described
in section \ref{descriptor-menu}.
In the descriptor-menu the descriptor of the current database is shown.
In it are commands to modify fieldnames and constraint patterns.

\subsubsection{Project}\label{project}

{\em Project\/} enables you to make a new database consisting of certain
columns of the current database.
It shows the names of the columns you can choose.
You can {\em select\/} a column and {\em delete\/} it again later.
The ranking of the selected columns is shown.
You can {\em increment\/} and {\em decrement\/} the ranking of a column.
With {\em show\/} you can get the current rank list.
Finish selection with {\em quit\/}.
With \TAB{} (or {\em exit\/}) you can exit {\em Project\/} altogether.

Deleted records, kept for retrieval, are projected too.

\subsubsection{Join}

{\em Join\/} enables you to make a new database by joining the current
database with another one.
It asks for another database to join with.
With \KEYUP{} and \KEYDOWN{} you can step through names
of databases you joined with earlier.
By typing \TAB{} you can exit {\em Join\/} altogether.

When joining databases $a$ and $b$, Jinx looks at the columns
with names that appear both in $a$ and $b$.
The join-key of a record consists of the concatenation of such fields.

When join detects a record in $a$ with a join-key that doesn't appear
in $b$ it asks you whether you want to {\em delete\/} the record from
the join or to {\em add\/} empty data for the record.
You can also specify (with {\em Delete\/}) that such records must always
be left out of the join, or specify ({\em Add\/}) that empty data
is to be added for all such records that may appear.

When join detects a record in $a$ with a join-key
that appears more than once in $b$ it asks you what to do.
You can specify that you wish to {\em add all\/} records of $b$ in the join.
You can also specify ({\em delete\/}) to leave that record out of the join.
Alternatively, you can specify ({\em Add\/}) that such records in $a$ must be
joined with all proper records in $b$, or specify ({\em Delete\/})
that all such records in $a$ should be left out of the join.

You may also choose {\em show\/}.
This option shows you the records in $b$ that can be joined with.
You can then {\em select\/} one, or mark select a subset in various ways.
This is described in detail in the section on selection (\ref{select-menu}).

When join detects a record in the current database with zero
or more than one records in $b$ to join with you may also {\em quit\/}
the entire join operation.

Deleted records don't take part in the join and are discarded.

\subsubsection{Order}

{\em Order\/} allows you to sort the database.
It shows the names of the columns so you can choose them as sort keys.
It is in fact the same selection process as is used in {\em Project\/}
(section~\ref{project}).

You can {\em select\/} a fieldname and {\em delete\/} it again later.
The ranking of the selected fieldnames is shown.
You can {\em increment\/} and {\em decrement\/} the ranking of a fieldname.
With {\em show\/} you can get the current rank list.
Finish selection with {\em quit\/}.
Select \TAB{} (or {\em exit\/}) if you don't want to {\em Order\/} after all.

When you don't select any fieldname as a sortkey, records will
be sorted in lexicographical order.

\subsubsection{Test all}\label{Test all}

{\em Test all\/} matches all fields of all records with
their constraint patterns.
Testing is started with the current record.
When a mismatch occurs, the record is shown.
The cursor points to the mismatching field and a message is given.
You can choose to search for the {\em next\/} mismatch,
search for the {\em Next\/} record with a mismatch,
{\em update\/} the current record,
or {\em quit\/} testing.

\subsubsection{Add field}

{\em Add Field\/} allows you to add a new field to the current database.
You will be asked for a fieldname, a constraint pattern and a default
value for the new field.
With \KEYUP{} and \KEYDOWN{} you can step through names, patterns and
values entered earlier.
Typing \TAB{} will abort the operation.
Fieldnames must be unique.

The current database will be made nameless because the descriptor
was modified.
The data will be marked {\em modified\/}.

\subsubsection{save}

With {\em save\/} you can write the current database to disk.
The current database must have a name {\em name\/}.
The data is written to {\em name\/\tt.dat}.
The previous data file (if any) is moved to a {\em name\/\tt.dat.save}.
Because the descriptor is not modified,
{\em name\/\tt.des} is not written to.

\subsubsection{Save as}

With {\em Save as\/} you can write the current database to disk.
The current database may be nameless.
You will be asked to provide a {\em name\/}.
With \KEYUP{} and \KEYDOWN{} you can step through names entered earlier.
With \TAB{} you can abort the {\em Save as\/} operation.
The descriptor will be written to {\em name\/\tt.des},
and the data will be written to {\em name\/\tt.dat}.
The previous descriptor and/or data (if any) are moved to 
{\em name\/\tt.des.save} and {\em name\/\tt.dat.save}.
The format of these files is described in the section 
on implementation (\ref{implementation}).

If the current database is nameless,
{\em Save as\/} will make {\em name\/} the name of the current database.
If the current database has a name and is marked {\em modified\/},
{\em Save as\/} will not mark the current database as {\em not modified\/}.

\subsubsection{open}

With {\em open\/} you can read in a database from disk
to make it the current database.
You will be asked to provide a {\em name\/}.
With \KEYUP{} and \KEYDOWN{} you can step through names entered earlier.
With \TAB{} you can abort the {\em open\/} operation.

\subsubsection{Guess}

With {\em Guess\/} you can build a Jinx database from data which already
looks like a Jinx database.
You will be asked for the name of a file and a pattern.
With \KEYUP{} and \KEYDOWN{} you can step through names entered earlier.
With \TAB{} you can abort the {\em Guess\/} operation.

The file is opened for reading.
Each line in the file is interpreted as a record and split
into fields with the pattern.
A descriptor with enough fields is generated.
Fields are named {\tt fieldname1}, {\tt fieldname2}, etc.
The default pattern is `{\tt .*}'.

You can make an example database with {\em Guess\/}
using file {\tt /etc/passwd} and pattern `{\tt :}'.

\subsubsection{Clear}

With {\em Clear\/} you can make Jinx forget about the current database:
no name, no data, no descriptor anymore.

\subsubsection{quit}

With {\em quit\/} you can leave Jinx.
You will be warned if the current database is marked {\em modified\/}.

\subsubsection{Quit}

Use {\em Quit\/} to leave Jinx without further ado.

\subsection{The main-menu}\label{main-menu}

After {\em inspect\/} in the meta-menu, Jinx shows the main-menu.
It presents commands which operate on the current database
on a record-by-record basis.
The data part of the screen will show (part of) the current record,
one field per line.
When you have ``long'' fields that don't fit on the screen,
you can move the view on the record to the right (left) with
\KEYRIGHT{} (\KEYLEFT).

You can move to the next (previous) record with
{\em prev\/} ({\em next\/}).
The current field is indicated by a `{\tt >}' in the first column.
Move to the next (previous) field with \KEYDOWN{} (\KEYUP).

\subsubsection{goto}

The {\em goto\/} command asks for a record number
and makes it the current record.
You can use $+N$ and $-N$ to indicate a number relative
to the number of the current record.
Finish entering the number with \RET.
With \KEYUP{} and \KEYDOWN{} you can step through numbers entered previously.
With \TAB{} you can indicate that you don't want to {\em goto\/} after all.

\subsubsection{search}

The {\em search\/} command asks for a search pattern and tries to find a match.
First it looks at the fields following the current field.
If this fails, it matches following records.
If this fails too, it matches preceeding records.
If a record matches the pattern, it is made the current record and
the matching field is made the current field.
Finish entering the pattern with \RET.
With \KEYUP{} and \KEYDOWN{} you can step through patterns entered previously.
With \TAB{} you can indicate that you don't want to {\em search\/} after all.

\subsubsection{re-search}

The {\em re-search\/} command repeats the last search command.

\subsubsection{update}\label{update}

Choosing {\em update\/} lets you modify the current record.
Move to a previous (next) field with \KEYUP{} (\KEYDOWN{} or \RET).
Finish editing the record with \TAB{}.
If you modify a field, the field will be checked with the
constraint pattern for that field.
If a mismatch occurs you are asked what to do.
You can {\em edit\/} the field again,
or you can tell Jinx to {\em forget\/} about the modification and leave
the field as it was.
You can also tell Jinx to {\em accept\/} the field as it is,
ignoring the mismatch.
You may also {\em quit\/} the entire update operation,
leaving the record as it was.

After you finish editing the record with \TAB{}
you will be asked to confirm the update.
Again, you may {\em edit\/} some more,
{\em accept\/} the record as it is,
or tell Jinx to {\em forget\/} about the update.

Only the modified fields are checked.
If some `improper' field value was accepted earlier,
Jinx won't complain as if that value isn't changed.

\subsubsection{add}

With {\em add\/} you can enter a new record.
You are presented with an empty record that you can modify
as with {\em update\/}.
When you finish editing (with \TAB), Jinx will ask you what to do if
there are `improper' empty values that you haven't explicitly accepted
in the current {\em add\/} operation.

\subsubsection{copy}

With {\em copy\/} you can enter a new record.
You are presented with a copy of the current record
that you can be modified as with {\em update\/}.
When you finish editing (with \TAB), Jinx will ask you what to do if
there are `improper' values that you haven't explicitly accepted
in the current {\em copy\/} operation.

\subsubsection{delete}

With {\em delete\/} you can delete the current record.

\subsubsection{test}

The {\em test\/} command matches all fields of the current record
with the corresponding constraint patterns.

\subsubsection{Test all}

{\em Test all\/} works like the same command in the meta-menu
(section \ref{Test all}).
It matches all fields of all records with their constraint patterns.
Testing is started with the current record.
When a mismatch occurs, the record is shown.
The cursor points to the mismatching field and a message is given.
You can choose to search for the {\em next\/} mismatch,
search for the {\em Next\/} record with a mismatch,
{\em update\/} the current record, or {\em quit\/} testing.

\subsubsection{Extract}

{\em Extract\/} lets you mark and select a subset of the records in the
database with the select-menu (see~\ref{select-menu}).
All but the selected records are deleted.
For safety, the current database is made nameless.

\subsubsection{Delete}

{\em Delete\/} lets you mark and select a subset of the records in the
database with the select-menu (see~\ref{select-menu}).
All the selected records are deleted.

\subsubsection{Undo}

{\em Undo\/} lets you mark and select a subset of the deleted records
with the select-menu (see~\ref{select-menu}).
All the selected records are put back in the database again.
Jinx forgets about deleted records if you scratch the current database
by opening another one, joining, etc.

\subsubsection{Compute}

{\em Compute\/} lets you compute new values in the database.
You can enter a Perl expression for each field.
For each field, the default expression shown is the last non-empty
expression entered earlier in the session for that field.
When doing the computation, empty expressions are ignored.
An expression consisting only of white space is an error.
To be precise, if expression {\em expr\/} is specified for field
{\em fieldname\/}, the result of
\begin{quote}
\tt do \{ {\em expr} ; \}
\end{quote}
is assigned to field {\em fieldname\/},
so {\em expr\/} may actually be a list of statements.
Assignment to the current record is done after all the expressions are
evaluated.

The expression is evaluated in a context where the following variables
are defined:
\begin{quote}
\begin{tabular}{|l|l|}\hline
\tt \_\_RECNUM\_\_    & record number of the current record \\
\tt \${\em fieldname} & value of field {\em fieldname\/} in the current record \\
\hline
\end{tabular}
\end{quote}
During the computation for one record, these variables keep their value
unless you change them yourself.
In the deleted records, new fieldvalues are computed too.

I wanted to include the following but the implementation caused Perl to crash.
\begin{quote}
Before the computation of the first record, a {\tt reset('[a-z]')} is done.
This implies that variables starting with a lower-case letter are reset,
while variables starting with an upper-case letter retain their value
from one {\em Compute\/} to another.
\end{quote}
It will be included in Jinx as soon as the patch comes out.

{\em Compute\/} can screw up Jinx and your data in many ways.
Introducing \TAB{}s and/or newlines will ruin the presentation.
Introducing newlines in fields will corrupt the record structure when you
write the database to disk.
Accessing variables in package {\em main\/} may crash Jinx.
\\
It is hard to decide what action to take if something like this happens.
One thing has been taken care of though.
If a computed field value contains the value of {\em \$;\/},
it is replaced by {\tt \$;} because {\em \$;\/} is unsed in Jinx as a
field separator in records.

There is no way (yet) to access fields in other records than the current record.
Also it is not (yet) possible to bind an expression to a field from one session
to another.

\subsubsection{Peek}

{\em Peek\/} lets you read records from another database.
It asks for the name of a database {\em other\/}.
After opening {\em other\/}, it lets you mark and select a subset
of the records in {\em other\/} with the select-menu (see~\ref{select-menu}).
In the select-menu, fieldnames in {\em other\/} that do not appear in the
current database are preceeded by two underscores ({\tt \_\_}).
These fields will not be copied to the current database
because there is no column for them.
Selected records of {\em other\/} are added at the end of the current database,
but some sort of projection and reshufle of fields is done first.
Only the fields with a name appearing in the current database are copied,
others are left out.
Empty data is added for fields in the current database that do not appear
in {\em other\/}.
This implies that you can only Peek at a database which has one or more
fieldnames in common with the current database.
From those databases, only the data in columns with common names can be copied.

\subsubsection{Read}

{\em Read\/} works like {\em Peek\/} except that it strips from
{\em other\/} those records which are already in the current database.

\subsubsection{Key test}

{\em Key test\/} lets you run a uniqueness test on the current database.
You are asked to select one or more fields in the current database
(just as in {\em Order\/} and {\em Project\/}).
{\em Key test\/} combines these fields for each record to produce a key for
each record.
Then it tests if every record has different key.
If some records have the same key, you enter a menu where you can
specify (with {\em show to delete\/}) that you want to select some records
for deletion. (See section~\ref{select-menu} on how to make a selection.)
Alternatively, you can ask for the {\em next\/}
key which appears in more that one record,
or {\em quit\/} the {\em Key test\/} operation deleting records as indicated sofar,
or {\em exit\/} the operation without any change.

If you don't select any fields, {\em Key test\/} will report on records
that appear two or more times in the current database.

\subsubsection{quit}

With {\em quit\/} you can leave the main-menu.

\subsubsection{Quit}

With {\em Quit\/} (or \TAB) you leave Jinx without further ado.

\subsection{The select-menu}\label{select-menu}

The select-menu lets you select records from a list of records.
Depending on the context, selected records will be used by
{\em Delete\/}, {\em Extract\/}, {\em Undo\/}, {\em Join\/}, etc.

In the select-menu, records are presented as in the main-menu.
You can order the {\em next\/} or {\em previous\/} record,
{\em search\/} with a pattern and {\em re-search\/},
or {\em goto\/} a record with a specific number.

A record is either {\em marked\/} or {\em unmarked\/}.
Initially all records are unmarked.
With {\em toggle\/} you can change the marking of the current record.
{\em Toggle\/} toggles the marking of all records.
{\em Clear\/} makes all records unmarked again.
Use ({\em Clear\/},{\em Toggle\/}) to mark all records.

With {\em Mark\/} you can specify a pattern (regular expression) for each field.
Every record with a field matching the corresponding pattern is marked.
Empty patterns are left out of the marking process.
{\em Unmark\/} is like {\em Mark\/} except that marks are removed.

With `{\tt <}' ({\em previous mark\/}) and `{\tt >}' ({\em next mark\/}) you
can step through the records marked sofar.
With `{\tt (}' ({\em previous unmark\/}) and `{\tt )}' ({\em next unmark\/}) you
can step through the unmarked records.

When you are done marking, you can either {\em select\/} the current record,
{\em Select all\/} marked records, or {\em quit\/} to abort the selection
process altogether.

\subsection{The descriptor-menu}\label{descriptor-menu}

After {\em Descr\/} in the meta-menu, Jinx shows the descriptor-menu.
It presents commands which allow you to change the attributes 
(fieldnames and constraint patterns) of the columns in the current database.
The data part of the screen will show the fieldnames
and constraint patterns of the descriptor.
The current fieldname is indicated by a `{\tt >}' in the first column.
Move to the next (previous) fieldname with \KEYDOWN{} (\KEYUP).

You can leave the descriptor-menu with {\em quit\/}.
With \TAB{} (or {\em exit\/}) you can abandon all modifications.

If you modify the descriptor, the current database will be made nameless
because the descriptor on disk (if any) is not in accordance with the
descriptor of the current database.

\subsubsection{pat edit}

With {\em pat edit\/} you enter edit-mode in which
you can edit the constraint patterns like ordinary field-values
(see section~\ref{update} on updating).
The only difference is that you can only enter valid regular expressions.
You can't make Jinx {\em accept\/} illegal regular expressions.

\subsubsection{name edit}

With {\em name edit\/} you enter edit-mode in which
you can edit the fieldnames like ordinary field-values
(see section~\ref{update} on updating).
The only difference is that you can only enter unique alphanumeric fieldnames.
You can't make Jinx {\em accept\/} illegal fieldnames.

\section{Tools}

See {\tt man jinx} for the description of some support tools.

\section{Examples}\label{examples}

Start up Jinx by simply typing {\tt jinx}.
When you don't have a Jinx database ready, make one with {\em Guess\/}.
Try file {\tt /etc/passwd} with separator `{\tt :}'.
Write the database to disk with {\em Save as\/} as {\tt blob}.
Update the descriptor with {\em Descr\/}.
Change the names into something meaningful.
Now, make two new databases {\em hidden\/} and {\em rest\/} consisting of 
the (login,passwd) columns and of the (login,uid,gid,name,home,shell) columns.
If you succeed, try to {\em Join\/} them again
and save the result as {\tt blib}. 
Diff {\tt blob.dat} and {\tt blib.dat}.
They should be the same.

Now, suppose a computer science department has a secretary where students
go when they come to study.
Every student has a student-card with a unique number on it. 
The secretary keeps an address database mapping card-ids to info about
the bearer like name, address, etc.
\\
Suppose a teacher wants to keep a record of every student following
some course.
The teacher can open the address database and extract the relevant records,
project out the irrelevant fields, add some new fields, and save it as the
course database.
If a student comes to enroll later, the teacher can Read in the
address database again to add the student's record to the course database.

\section{Implementation}\label{implementation}

A Jinx-database is represented on disk as follows.
The file {\em name\/\tt.des} contains lines of text like
\begin{quote}
\em attribute-name \tt: \em column-number \tt: \em attribute-value
\end{quote}
where {\em attribute-name\/} can be {\tt name} or {\tt cpat}.
The corresponding {\em attribute-values\/} represent fieldnames
and constraint patterns for column {\em column-number\/}.
Other attributes may be introduced later.

The file {\em name\/\tt.dat} contains lines of text, one for each record.

In both files fields are separated by a colon (`{\tt :}').
The colons in user data and attribute values are escaped
by exclamation marks (`{\tt !}'),
as are the exclamation marks in user data and attribute values.
(I know I could have used tabs as field separators and no escapes
since tabs are forbidden in user data anyway.
I didn't because I hate tabs and wanted to keep the files readable~:--).

Various things may change sooner or later.
However, the format of the files is flexible enough
to allow transparant upgrades.

\section{Installation}\label{installation}

Jinx requires the {\em cterm\/} package which provides an interface
to {\em curses\/}.
Jinx requires that your curses must be able to recognize arrow-keys.
Plain BSD-curses is not good enough. Cterm works fine on HP/UX,
Ultrix, SunOs (if /usr/5bin/cc is used) and others.
Jinx also requires plain Perl (PL18 and up).

Install cterm if you don't have it.
See section~\ref{how-to-get} on how to get it.
Unpack the Jinx stuff in a separate directory.
If your Perl isn't in {\tt /local/bin/perl},
change the first line in {\tt jinx}, {\tt Jjoin}, {\tt Jlist},
{\tt Jproject}, {\tt Jreport} and {\tt Jsort} to the proper {\tt \#!}-line.

Start Jinx by typing {\tt jinx}.
This may take some time.
Jinx checks cterm to see if all the necessary curses functions
and constants are defined in the cterm interface.
Leave Jinx with `{\tt q}' if it starts up without complaining.

Study the Makefile.
Edit the variables \mbox{\tt PERLLIB} and \mbox{\tt BINDIR}.
They determine where the Perl libraries and programs go.
Edit the variables \mbox{\tt LIBMODE} and \mbox{\tt BINMODE}.
They determine the permissions of the installed Perl libraries and programs.
Edit the names of the programs used in the Makefile if necessary.

If you have undump, make a binary version of Jinx with \mbox{\tt make dump}.
Install Jinx with \mbox{\tt make dump-install} if you are successful.
If you don't have undump, install Jinx with \mbox{\tt make install}.
Install the manual page \mbox{\tt jinx.1} by hand.
If you have \LaTeX, do \mbox{\tt make doc} and print \mbox{\tt jinx.dvi}.
If not, pick up a PostScript version of the tutorial \mbox{\tt jinx.ps}.
Read it and/or play.

\section{How to get Jinx/cterm}\label{how-to-get}

Jinx, a (PostScript) jinx tutorial, and cterm are ftp'able from
\mbox{sol.cs.ruu.nl} (\mbox{\tt 131.211.80.5}).
Look in directory \mbox{\tt pub/UNIX} for the files
\mbox{\tt jinx.shar.Z}, \mbox{\tt jinx.ps.Z}, and \mbox{\tt cterm.shar.Z}.
If you don't have access to ftp,
send a message to \mbox{\tt mail-server@cs.ruu.nl} containing:
\begin{quote}\tt
send cterm.shar\\
send jinx.shar\\
send jinx.ps\\
end
\end{quote}
The compressed, uuencoded stuff will be sent to you.

\section{Copyright, Warranty}

\begin{verbatim}

         Jinx, Copyright (c) 1990, Henk P. Penning

Jinx is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 1,
or (at your option) any later version.

Jinx is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
\end{verbatim}

\end{document}

