5.4. The Cascade Compatible Cogent Driver manuals

These Cogent Driver manuals are an experiment in single-sourcing. The idea is to have one core manual with generic content, that describes the universal features and functions of a hypothetical generic driver. Then, like the product, each specific instantiation of the generic driver, such as the CIF Driver, has its own manual that adds its own specific material to the generic material. With single-sourcing, we can integrate generic material so seamlessly into the driver-specific manual that it appears to be a 100% specific manual. The generic content itself is not distributed as such, but can be generated as the Cogent Driver manual if necessary.

To achieve this goal, we use a wrapper for each book, (doc/i/xxdriver/wrapper.sgml) that contains entities that point to the generic content, as well as the text of the specific content for the book's chapters. Each book also has a reference (doc/i/xxdriver/reference.sgml) that contains the necessary generic and specific reference entries. Each reference entry corresponds to one driver command. Most commands are either generic to all drivers, or specific to a certain driver, but a few of the generic commands have specific information pertaining to a specific driver. For these few, we are currently creating a separate reference entry. (This may not be true single-sourcing, but it greatly simplifies the production and maintenance of the document right now. We may change this in the future if it turns out to be more trouble than it's worth.)

Each book uses two sets of entity definitions—generic and specific. The generic entities are defined in doc/i/gendriver/entities.sgml and the specific entities, such as for the CIF Driver manual are defined in doc/i/cfdriver/entities.sgml file. In addition to the book's specific entities, the entities.sgml file for each book also defines the wrapper and reference for that book.

To generate each book according to the correct entities, the doc/o/drxx-book/main file calls both the generic and specific entity definition files, bringing together the generic and specific material.

Here is an example of corresponding parts of the generic entity definition file, the CIF entity definition file, the CIF reference file, and the CIF main.sgml output file:

Generic entities: doc/i/gendriver/entities.sgml

These are some of the generic reference entries.

...

<!entity version SYSTEM "re_version.sgml">
<!entity write SYSTEM "re_write.sgml">
<!entity writable SYSTEM "re_writable.sgml">

CIF-specific entities: doc/i/cfdriver/entities.sgml

This shows the entities for the wrapper and reference, and a few specific reference entries. All CIF-specific versions of generic entities start with the two letters "cf".

<!entity cfwrapper  SYSTEM "wrapper.sgml">
<!entity cfreference  SYSTEM "reference.sgml">
...

<!entity cfwrite SYSTEM "re_write.sgml">

CIF reference: doc/i/cfdriver/reference.sgml

This shows how the generic and specific reference entries are called within the reference. Notice how the "cf" version of write is called.

<reference>
  ...

  &version;
  &cfwrite;
  &writable;
</reference>

CIF output: doc/o/drcf-book/main.sgml

This file defines and calls both the generic and CIF-specific entities in the header. Then it calls the CIF wrapper and reference in the <book> element.

...

<!ENTITY % cfentities SYSTEM "../../i/cfdriver/entities.sgml"> %cifentities;
<!ENTITY % genentities SYSTEM "../../i/gendriver/entities.sgml"> %genentities;
...

<book>
	&cfwrapper;
	&cfreference;
	&index;
</book>

As mentioned above, some reference entries have two source files, a generic version and a specific version. For example, in the CIF Driver manual the generic write reference page has specific content, so there is a separate files for it in the doc/i/cfdriver/ directory. And there are specific entities for it (cfwrite) in the cfdriver/entities.sgml file, which is called in turn by the cfdriver/reference.sgml file, instead of the generic command of the same name.

ID conflict in the bookset

This system works OK until you want to include two or more driver manuals in one document, ie. the Cogent Documentation bookset. Since there is a lot of common material in several books you would get duplicate IDs, which is invalid SGML because each SGML element within a single document must have its own ID.

To solve this problem, we have a special makefile called copydrivers.mak that is called by the doc/o/cogent-set/Makefile. This makefile contains sed scripts that replace all the IDs (like "dr-refentry") and references to them with specific IDs (like "drcf-refentry" for the CIF Driver).

Each driver manual has an extra set of entity definitions just for the bookset, called setentities.sgml. This file contains all the entities in the driver's entities.sgml file, plus all the entities in the generic entities.sgml file. The generic entities in that file each have the two-letter prefix for that particular driver appended to their name.

In like manner, each specific driver manual in the bookset also has a setreference.sgml file that calls the entities in the setentities.sgml file. The doc/o/cogent-set/main.sgml file only references the setentities.sgml files, and thus only "sees" those special entities.

Compare the arrangement of entities below with that given in the example above.

CIF entities for the bookset: cfdriver/setentities.sgml

<!entity cfwrapper  SYSTEM "wrapper.sgml">
<!entity cfreference  SYSTEM "setreference.sgml">
...

<!entity cfwrite SYSTEM "bookset/re_write.sgml">
...

<!entity cfversion SYSTEM "bookset/re_version.sgml">
<!entity cfwritable SYSTEM "bookset/re_writable.sgml">

CIF reference for the bookset: cfdriver/setreference.sgml

<reference>
  ...

  &cfversion;
  &cfwrite;
  &cfwritable;
</reference>