home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume43
/
prg
/
part01
next >
Wrap
Internet Message Format
|
1994-06-10
|
79KB
From: patsch@ubka.uni-karlsruhe.de (Patrick Dockhorn)
Newsgroups: comp.sources.misc
Subject: v43i032: prg - PostScript report generator V1.1, Part01/06
Date: 10 Jun 1994 10:22:15 -0500
Organization: University of Karlsruhe, Germany
Sender: kent@sparky.sterling.com
Approved: kent@sparky.sterling.com
Message-ID: <csm-v43i032=prg.102120@sparky.sterling.com>
X-Md4-Signature: 25fd09f064b48b1e6f3f6fce494ac994
Submitted-by: patsch@ubka.uni-karlsruhe.de (Patrick Dockhorn)
Posting-number: Volume 43, Issue 32
Archive-name: prg/part01
Environment: postscript, UNIX
WHAT IS PRG ?
prg is a PostScript report generator based on generic input data. The
data consists of two parts: A description file and a data file. The
first file describes the logical structure of the data file.
prg can be used to manage all kinds of data, like your personal phone
book, addresses, books, music cassettes and so on. Once you've entered
your data you can create reports that contain an arbitrary combination
of fields from your data and you may sort them by whatever keys you
want. You may also retrieve only a subset of the records stored in
the data file; prg contains a parser for simple selection expressions
to support this.
PRG runs in a UNIX environment; it only requires standard-tools
(awk, shell...), there's no need for any compiler.
WHAT'S NEW IN RELEASE 1.1 :
1. MAJOR NEW FEATURES
1.1. SELECTORS ADDED:
It is now possible to print a report of a selection of records only.
The selection is implemented as an expression that is parsed at
runtime to determine whether a record qualifies for a report or not.
See the new SELECTION section in the OnLine-Documentation and the
manual page for details.
1.2. ONLINE-HELP:
You may now query prg for the meaning of any of its parameters using
the '-info yourOption' option, i.e.
prg -info -select
shows you information about the '-select' option.
1.3. SUPPORTING LARGE DATA FILES
The PostScript code has been rewritten in order to support arbitrary
large data files.
2. MINOR NEW FEATURES
2.1. Time-Field allows seconds to be used if field data is preceeded by 's'
2.2. If you want hash characters in your strings replace them by '\hash'
2.3. If a column has the same contents for two succeeding rows i and i+1
you may want to use the option '-noDuplicates' to avoid the repetitive
printing of this identical contents.
2.4. If the contents of the first column change, a delimiting horizontal
line is drawn between these two rows.
2.5. Enhanced handling of time fields (option '-accuracy' added).
2.6. The command line used to produce the program now appears on the
title page.
WHERE TO GET IT:
The new release 1.1 is currently available from the ftp site
ftp.ubka.uni-karlsruhe.de
in the directory
/pub/prg
Get the file prg-1.1.tar.gz using binary transfer mode.
If you have any comments, find bugs etc., drop me a line.
-patsch
--
Patrick Dockhorn \ Uni-Bibliothek \ Kaiserstrasse 12 \ 76131 Karlsruhe \
\ e-mail: patsch@ubka.uni-karlsruhe.de,finger=ubkaaix3\ Germany __o \
\ There are two rules for success in life: \ _`\<,_ \
\ Rule 1: Don't tell people everything you know. \ (_)/ (_) \
------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: prg prg/INDEX prg/data prg/doc prg/lib prg/man prg/prg
# Wrapped by kent@sparky on Thu Jun 9 12:32:32 1994
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 1 (of 6)."'
if test ! -d 'prg' ; then
echo shar: Creating directory \"'prg'\"
mkdir 'prg'
fi
if test -f 'prg/INDEX' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'prg/INDEX'\"
else
echo shar: Extracting \"'prg/INDEX'\" \(949 characters\)
sed "s/^X//" >'prg/INDEX' <<'END_OF_FILE'
XINDEX - List of files contained in the 'prg' distribution:
X----------------------------------------------------------
X
XINDEX This file
XINSTALL Notes on how to install prg on your system
XREADME Introduction to prg
Xprg patsch's PostScript report generator, shell script
X
Xdata/videos Example data, movie collection on video tapes
Xdata/videos.des Description file for the movie collection
X
Xdoc/prg.1.ps Manual page in PostScript format
Xdoc/prg.5.ps Manual page for the prg file format in PostScript
Xdoc/videos-by-actors.ps Sample report, see EXAMPLES section
Xdoc/videos-by-length.ps Sample report, see EXAMPLES section
Xdoc/videos-by-number.ps Sample report, see EXAMPLES section
X
Xlib/prg.awk AWK program that does most of the extraction work
Xlib/prg.sed SED skript that provides for the correct representation
X of german umlauts
X
Xman/prg.1 Manual page for the PostScript report generator
Xman/prg.5 Manual page for the data files related to prg
X
END_OF_FILE
if test 949 -ne `wc -c <'prg/INDEX'`; then
echo shar: \"'prg/INDEX'\" unpacked with wrong size!
fi
# end of 'prg/INDEX'
fi
if test ! -d 'prg/data' ; then
echo shar: Creating directory \"'prg/data'\"
mkdir 'prg/data'
fi
if test ! -d 'prg/doc' ; then
echo shar: Creating directory \"'prg/doc'\"
mkdir 'prg/doc'
fi
if test ! -d 'prg/lib' ; then
echo shar: Creating directory \"'prg/lib'\"
mkdir 'prg/lib'
fi
if test ! -d 'prg/man' ; then
echo shar: Creating directory \"'prg/man'\"
mkdir 'prg/man'
fi
if test -f 'prg/prg' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'prg/prg'\"
else
echo shar: Extracting \"'prg/prg'\" \(70190 characters\)
sed "s/^X//" >'prg/prg' <<'END_OF_FILE'
X#!/bin/sh
X
X############################################################
X# #
X# prg - PostScript Report Generator #
X# Creates a PostScript report of my videos or #
X# anything else defined by a description and #
X# a data file in the prg format. #
X# #
X# Written in late May 1994 by patsch. #
X# #
X# To get an idea about what prg can do, try the #
X# example database provided. #
X# #
X# Further information about the program can be #
X# found in the manual page provided, or by #
X# supplying one of the following options: #
X# -help #
X# -info guide #
X# -info options #
X# -info usage #
X# -info files #
X# #
X# #
X# The main part of the shell skript can be found #
X# by searching for 'prgmain'. #
X# #
X# !---------------------------------------------------! #
X# ! ! #
X# ! Copyright (C) 1994, Patrick Dockhorn. ! #
X# ! ! #
X# ! Permission to use and modify this software and ! #
X# ! its documentation for any purpose other than ! #
X# ! its incorporation into a commercial product is ! #
X# ! hereby granted without fee. Permission to copy ! #
X# ! and distribute this software and its ! #
X# ! documentation only for non-commercial use is ! #
X# ! also granted without fee, provided, however, ! #
X# ! that the above copyright notice appear in all ! #
X# ! copies, that both that copyright notice and ! #
X# ! this permission notice appear in supporting ! #
X# ! documentation. The author makes no ! #
X# ! representations about the suitability of this ! #
X# ! software for any purpose. It is provided ! #
X# ! ``as is'' without express or implied warranty. ! #
X# ! ! #
X# !---------------------------------------------------! #
X# #
X############################################################
X
X
X
X##################################################################
X#
X# CONFIGURATION: PLEASE ADJUST THESE VARIABLES TO YOUR NEEDS
X#
X#
X
X# define your awk program here
XAWK=awk
X
X# Path where the awk and sed programs that prg requires are located
XPRGLIBPATH=./lib
X
X# Path with the data and description files
XPRGDATAPATH=./data
X
X# Path for temporary files, you need write access there !
XTMPDIR=.
X
X#
X# DEFAULT VALUES FOR THE COMMAND LINE OPTIONS
X#
X
X# data and description file
XINFILE=${PRGDATAPATH}/videos
XDESFILE=${PRGDATAPATH}/videos.des
X
XFONTNAME=AvantGarde-Book
XFONTSIZE=12
X
X# Active output columns
XFORMAT=NUM#IDX#TIT#ACT#CAT#LEN#OFF
X
X# Sort keys
XSORTBY=NUM#IDX
X
X# Default: Select all
X# Use
X# -select 'TIT=="Michae*"'
X# to select only those entries where the TIT field
X# starts with Michae
X# See the manual page or the online docu for the
X# exact specification of a selector.
XSELECT=""
X
X# title of the report
XTITLE="Videoliste"
X
X# AWK debugging is off
XDEBUG=0
X
X# AWK expression debugging is off
XDEBUGEXPR=0
X
X# PostScript debugging is off as well
XDEBUG_PS="false"
X
X# Optimization is on by default
XOPTIMIZE="true"
X
X# delimiter string
XDELIMITER=", "
X
X# by default the title is default
XSHOWTITLE="true"
X
X# default unit is cm,
X# therefore this is the multiplication factor for points
XUNIT=28.346456
X
X# comparison for sorting is not case sensitive by default
XCASECOMP=0
X
X# print in portrait or landscape mode ?
XLANDSCAPE="false"
X
X# Width and Height of the physical page
X# The defaults represent DIN A4.
X
XPAGEWIDTH="21.0 cm"
XPAGEHEIGHT="29.7 cm"
X
X# security offset from left and bottom margin
X# to prevent any objects from being invisible
X# due to the printers lack of displaying them
X# in extreme positions
X
XHOFF="1.2 cm" # horizontal skip (used with left AND right margins)
XVOFF="1.2 cm" # vertical skip (used with top AND bottom margins)
X
X# If you attempt to print large amounts of data
X# the input has to be split into smaller chunks
X# in order to avoid a memory overflow in your
X# PostScript printer/interpreter.
X# If you encounter this problem please
X# decrease the value of the following variable.
X# It represents the maximum number of elements
X# an array within prg's PostScript engine may contain
X
XMAXARRAYSIZE=256
X
X# Default value for 'remove duplicate values in succeeding rows'
XNODUPLS="false"
X
X# Specify the accuracy of time fields.
X# Possible values are: seconds, minutes or hours
XACCURACY="seconds"
X
X# Compare By Sorting Criteria
X# If this flag is set, comparison for
X# string equality (during the selection)
X# is based on the entry as it is used for the
X# sorting process, i.e. with CBSC=1
X# (ACT == H*) would find the entry Anthony$Hopkins,
X# whereas with CBSC=0 it would not. It would
X# then for example find Harold$Ramis.
XCBSC=1
X
X# END OF CONFIGURABLE PART
X#
X###################################################################
X
X##################################################################
X#
X# functions
X#
X##################################################################
X
X
XHelp()
X{
X cat << END_OF_INTENTION
X
Xprg is a PostScript report generator based on generic input data.
XThe data consists of two parts: A description file and a data file.
XThe first file describes the logical structure of the data file.
X
Xprg was written originally to manage a collection of video tapes and
Xthis is where some of the 'specials', like the automatic computation
Xof offsets on tapes stems from. If you don't need those features,
Xsimply don't use them.
X
Xprg can be used to manage all kinds of data, like your personal phone
Xbook, addresses, books, music cassettes and so on. Once you've entered
Xyour data you can create reports that contain an arbitrary combination
Xof fields from your data and you may sort them by whatever keys you want.
X
XDetails about prg's command line options are displayed when giving the
X'-info usage' option. General hints about how to use the program are
Xshown with the '-info guide' option, the format of the description and
Xdata file are explained in detail when supplying the '-info files' option.
X
Xhave fun, If you have any comments, find bugs
X patsch or would like to add a feature,
X patsch@ubka.uni-karlsruhe.de please let me know !
X
XEND_OF_INTENTION
X}
X
XInfoGuide()
X{
Xcat << END_OF_GUIDE
X
X0. GETTING STARTED
X
XTake a look at the example files containing a video tape collection.
XYou may create a number of different reports by slightly varying the
Xparameters to prg. For example you might want to try:
X
Xprg videos -format ACT#TIT#NUM#IDX#DIR -sortby ACT#TIT
X
XThis creates a report sorted by the actors appearing in the videos.
XIf an actor appears in several movies, the entries are sorted using
Xthe movie titles.
X
XThe report contains the fields specified with the -format option.
XIf you take a look at the description file you'll see that they
Xcorrespond to Actors, Titles, the internal number of the video tape,
Xthe index of the movie on the specific tape and the director.
XAs the actor appears as a sort key, only one actor is shown in the
Xactor column.
X
XLet's try something else. We'll create a report of all the movies
Xsorted by number and index, i.e. a 'natural sort'. I'd like to see
Xa maximum of two actors as well as the title and the length of the
Xmovie. This file is created by
X
Xprg videos -format NUM#IDX#ACT-2#TIT#LEN -sortby NUM#IDX
X
XAs the NUM and IDX fields have the 'numeric' attribute, their contents
Xare shown justified to the right. We might as well get a list of all
Xthe movies with the longest movie first:
X
Xprg videos -format NUM#IDX#ACT-2#TIT#LEN -sortby -LEN
X
XNote the dash in front of the sort key, this indicates a reverse sort.
X
XNow that you got an idea of how prg works and what it can do, you might
Xwant to read the additional documentation in the following sections.
X
X------------------------------------------------------------------
X1. FILES
X------------------------------------------------------------------
X
X1.0 PROGRAMS
X
Xprg runs in a UNIX environment. It requires a number of standard
XUNIX tools to be present, otherwise it won't work.
XMost of these tools are available for other operating systems,
Xe.g. OS/2, as well, therefore you will be able to use prg with
Xthis operating systems as well.
XThe tools required are awk (or nawk or gawk), sed, cat, sort,
Xwc, basename, split and the bourne shell.
X
X1.1. INPUT FILES
X
Xprg looks for its input files, i.e. the description file and the data
Xfile, in the directory specified by PRGDATAPATH. This setting is
Xoverwritten if you specify another directory using the '-datapath
Xyour-data-directory' option on the command line. If the data file is
Xnot found there, prg looks for it in the current working directory. If
Xit still fails to locate the data file, it bails out. The description
Xfile name is built from the data file name by appending ".des"
XInformation about the format of the data and description file can be
Xobtained by specifying the '-info files' option.
X
X1.2. LIBRARY FILES
X
Xprg requires two library files to work. The first is an awk program
Xthat does the whole job of extracting the requested information and
Xfiddling it into an array that serves as an input to the PostScript
Xprogram. The second is a small sed program used to convert various
XUmlauts into their corresponding PostScript codes. This sed program
Xcan easily be extended to provided support for other languages as
Xwell. At the moment the German umlauts are supported. They may be
Xentered in LaTeX style as well as ISO Latin1 umlauts. prg searches
Xfor this library files in the path given by the variable PRGLIBPATH.
XYou may override this setting by specifying another directory through
Xthe command line option '-libpath your-directory'.
X
X1.3. OUTPUT FILE
X
Xprg always creates a PostScript file that, if sent to a PostScript
Xprinter, produces a formatted report of your data. This output file
Xis *ALWAYS* written into your current working directory, regardless
Xof the actual location of your data and library files.
X
X1.4 TEMPORARY FILES
X
Xprg creates a number of temporary files. These files are written into
Xthe directory you specify with the TMPDIR variable in the configuration
Xpart of prg. It is important that TMPDIR points to a directory where
Xyou have both read and write permission.
X
X------------------------------------------------------------------
X2. THE FORMAT SPECIFIER
X------------------------------------------------------------------
X
XWith prg you can select arbitrary members of your records to be
Xincluded in the output. You simply concatenate the individual
Xcolumn identifiers with a '#' character.
XLet's suppose you have defined a field ACT in your description file
X(like the actor field in the example movie collection).
X
XIf you specify this field in the format string, the corresponding data
Xis included in the report, usually in a column that is wide enough to
Xtake all the data present. This is something not desired, as you may
Xhave multiple entries within one field - as in the example. You may
Xspecify more than one actor in the ACT field of your records. If ACT
Xis a sort key as well, this doesn't pose a problem, as only the
Xcurrent sort key is displayed in the actor's column then. However, if
Xyou use another field as the sort key, you may want to see all the
Xactors you specified, causing the column to become *really* wide. By
Xdefault, only one element of a field that may contain more than one
Xelement is displayed - with the exception of a field of type
X'weightened selection'. With a weightened selection (like the
X'Category' field in the video collection) shortcuts for all the
Xpossible selections are displayed. If you want to see more than one
Xelement of a field holding several entries, you can specify the number
Xof desired entries by supplying a trailing dash followed by the
Xmaximum number of hits you would like to see.
X
XInstead of
X
Xprg -format ACT
X
Xyou write
X
Xprg -format ACT-3
X
XThen up to three actors would be displayed in the actors column,
Xdelimited by the standard delimiter, which you may want to change
Xeither in the configuration section of prg or by supplying the command
Xline option '-delimiter'.
X
XSometimes it may be necessary to neglect the optimized sizes prg
Xcomputes for you. It is therefore possible to specify for each
Xselected column the size of the column. Such a manual setting of a
Xcolumn's width always overrides the computed width, thus you can set
Xthe size of one column by hand while prg computes all the others in a
Xway that the resulting output still fits onto the paper. If you wanted
Xto restrict the size of the actor's column to 2 centimeter, you would
Xspecify
X
Xprg -format ACT:2#TIT#NUM#IDX
X
XIn this example the actor's column came out exactly 2 centimeters
Xwide, while all the others would be computed such that they would fit
Xonto the page. You may freely mix the width specifier ':' and the
Xfield multiplicity specifier '-'.
X
XNote that prg never allows two columns to overwrite each other, as the
Xoutput within a column is always clipped to the boundaries of that
Xcolumn. Therefore a column that's two small to hold all the data you
Xwant it to hold still makes sense and does produce a nice output.
X
X
X------------------------------------------------------------------
X3. THE SORT KEYS
X------------------------------------------------------------------
X
XYou specify the sort keys in the same way you do with the output
Xcolumns, i.e. by concatenating an arbitrary number of column
Xidentifiers with '#' characters, e.g.
X
X-sortby ACT#TIT
X
Xwould produce a report sorted by the contents of the ACT field.
XIf the contents of two ACT fields are identical, then the TIT
Xfields are used to identify the order of the two records.
X
XThe default is to order the entries ascending; if you want them
Xto be sorted descending preceed the corresponding column identifier
Xby a single dash, i.e.
X
X-sortby -ACT
X
Xproduces a report where the actors appear reverted, i.e. from Z to A.
X
XIf you specify a column representing a number or a time object, i.e.
Xwith type 'N' or 'T', the sorting is based on the arithmetic value of
Xthe columns rather than the characters.
X
X------------------------------------------------------------------
X4. SELECTION MECHANISM
X------------------------------------------------------------------
X
XFrom release 1.1 on, prg provides for a selection mechanism that
Xallows you to select only a subset of the records defined in your
Xdata file. The exact format of such a selector is the topic of
Xthis section. Selectors *have* to be present in a separate file,
Xas the simple parser expects spaces which are lost on the command line
X(any idea on how to avoid this ?). You specify the selector with
Xthe '-select filename' option. If you provide the filename 'stdin',
Xyou are prompted for the selector.
X
XA selector is an expression as described by the following 'grammar':
X
XOPERATOR: [ == | != | >= | <= | > | < | contains ]
X
XEXPRESSION: [ (FIELD-ID OPERATOR VALUE) | # simple test
X
X EXPRESSION || EXPRESSION | # OR
X
X EXPRESSION && EXPRESSION | # AND
X
X (EXPRESSION) | # forcing evaluation
X
X !EXPRESSION ] # negation
X
Xwhere FIELD-ID is one of the field identifiers you chose in your
Xdescription file, i.e. TIT, ACT, LEN... for the video data.
X
XVALUE is either a string or a numeric value; a string should be
Xenclosed in double quotes.
X
XThe 'contains' operator is useful for fields that may hold multiple values.
XIt checks whether the given values is at least present once in the field.
X
XHowever, if you specify a field with the Multi-Attribute 'M' as a sort key,
Xyou have to use the == operator; you may not use the contains operator.
X
X**********************************************************************
XThe usage of this expressions should be intuitive; however take care
Xto stick to the exact syntax. The expression parser isn't robust at
Xall - you might even say that it's worse than lint as far as checking
Xyour input is concerned. Don't put spaces before the first and after
Xthe second operand; always surround the operator by spaces.
X**********************************************************************
X
XYou may use the truncation character '*' to indicate that
Xthe expression yields true if the current field contains a
Xstring that's equal to the given value up to the asterisk;
Xotherwise an exact match is performed. This special feature
Xis available for the ==, != and contains operator.
X
XThe selection mechanism also interacts with the
X'-compareBySortingCriteria' or '-cbsc' option. It is useful
Xto determine whether a selector should use the actual entry
X(e.g. "Michael$Biehn") or the modified entry as it is printed
Xand used for sorting, i.e. "Biehn, Michael".
X
XExamples for selectors:
X
X(TIT == "Terminator") # selects all records where the TIT field
X # is Terminator
X
X(LEN > 120) # selects all movies longer than 2 hours
X
X(ACT == "Michael*") # all records with actors starting with Michael
X # NOTE: This expression is valid iff ACT is a
X # a sort key. Otherwise you would have to
X # use the contains-operator
X
XAll sequels of the Terminator series with Arnie:
X
X(ACT == "Arnold*") && (TIT=="Terminat*")
X
XAnd finally a rather complex example.
XNOTE: As long as you stick to the syntax, the recursive
X expression parser will eventually get the value for
X your expression. However, awk is an interpreter and
X this program is not optimized for speed, therefore
X complex operations will result in some delay...
X
X(((ACT == Wil*) && (DIR contains Mc*)) || (NUM == 2))
X
XThis means: Select all entries where
Xa) the actor field (which has to be a sort key, otherwise == is not allowed!)
X contains a value starting with 'Wil' and the director field contains at least
X one value starting with 'Mc'
Xor
Xb) the NUM field has the value 2.
X
X------------------------------------------------------------------
X5. SPECIALS
X------------------------------------------------------------------
X
XThere is a column identifier OFF, which stands for Offset, that is
Xuseful for the representation of any media like video tapes, cassette
Xtapes and compact discs. Provided that the records contain a LEN entry
Xof type 'T' (Time), the OFF entry of the record is automatically
Xcomputed by adding up all the LEN entries before the current entry on
Xthe current media. The media is identified by the NUM column whereas
Xthe logical position of the entry is determined by the order it
Xappears in the data file. This implies that, in order for the Offset
Xvalue to be correct, the movies on one tape have to be *in order* in
Xthe data file. I could have computed the correct offset value but this
Xwould imply having another pass through the whole array and as it is a
Xspecial anyway I thought that I might as well impose a rule on the
Xdata order to get the accurate offset value. I summarize: You should
Xnot specify a value for the OFF column in any record as it is computed
Xautomatically. However you are free to use this column of type 'Time'
Xin your reports by specifying it in the format string.
X
X------------------------------------------------------------------
X6. ADDING SUPPORT FOR A NEW LANGUAGE
X------------------------------------------------------------------
X
XIf you'd like to add support for a new language, i.e. special characters
Xthat do not appear in the standard PostScript character encodings, you
Xhave to do the following:
X
X- change the /germanvec vector which holds the modified encoding table
X for the german umlauts such that the available positions refer to the
X characters you'd like to see in the output. You need some knowledge
X of PostScript to do this.
X- extend the sed skript prg.sed such that your national characters are
X replaced by the corresponding PostScript octal codes.
X
X------------------------------------------------------------------
X7. KNOWN BUGS & NEW FEATURES
X------------------------------------------------------------------
X
XI implemented the whole prg project in a couple of days and therefore
Xthere'll be heaps of bugs and possibilities for improvevements -
Xstarting with the bad english used in this documentation :-)
X
XIf you find a bug or would like to have a feature added or if you
Xadded support for a new language (french umlauts etc.), please drop me
Xa note and I'll incorporate your ideas into the next release of prg.
X
XSend your messages to patsch@ubka.uni-karlsruhe.de
X
XHave fun !
X
X -patsch
X
XEND_OF_GUIDE
X}
X
XInfoFiles()
X{
Xcat << END_OF_FILEINFO
X
XThere are two types of data files required to run prg -
Xthe description file and the actual data file.
XThe description file, as the name implies, describes
Xthe format of the records in the data file. The data file
Xitself contains an arbitrary number of records. The name of
Xthe description file is always created by appending ".des"
Xto the name of the data file.
X
X------------------------------------------------------------------
X1. DESCRIPTION FILE
X------------------------------------------------------------------
X
XI'll use an excerpt of the example, the video tape collection,
Xto explain on how the description file is organized:
X
XBEGIN_DESCRIPTION
XNUM#Nr.#N#O
XIDX#Index#N#O
XDIR#Director#A#M
XPRO#Producer#A#M
XACT#Actor#A#M
XTIT#Title#A#O
XLEN#Length#T#O
XMOD#Record Mode#A#S#SP#LP
XCAT#Categories#A#W#_C_omedy#_A_ction#_Science_Fiction#_T_hriller
XEND_DESCRIPTION
X
X
XThe generic format of the description file is as follows:
XThe beginning of the description is identified by the keyword
X
XBEGIN_DESCRIPTION
X
XThe following field definition lines each describe one field (I also
Xuse the word 'column' for a field) in the record. The format for
Xthese lines is:
X
XfieldIdentifier#fieldName#fieldType#fieldMultiplicity#selections...
X
XAt the end we have the keyword
X
XEND_DESCRIPTION
X
XLet's examine the column definition lines. They consists of a number
Xof fields separated by a '#' character.
X
X1.1. fieldIdentifier
X
XThis is a string that you use to refer to the field within the format
Xstring, where you specify which fields should appear in the report.
XYou also use this shortcut within the specification of the sort keys.
XThe length of the field identifier is not restricted to three characters.
XHowever, the identifier should represent some sort of abbreviation for
Xthe field name.
X
X1.2. fieldName
X
XThe field name is the title of the field as it appears on top of each
Xpage when the column is printed. For example the field name of the
Xfield identified by ACT is Actor.
X
X1.3. fieldType
X
XThe data contained in the ACT field is alphanumeric, i.e. a string
Xcontaining characters and maybe numbers. I call this type 'A'.
XHowever, the LEN field indicating the length of the movie in minutes
Xis a numeric field, therefore it's field type is 'N'. This information
Xis used in two ways: First, a numeric column is always justified to
Xthe right when printed and second, the ordering of numeric data is
Xbased on its arithmetic value rather than the characters its build
Xfrom. For example: Using the standard sorting method, the data 1, 2
Xand 10 would be sorted into 1, 10, 2. If the corresponding column has
Xnumeric type, an arithmetic comparison takes place and the order is 1,
X2, 10. There is a third possible field type identified by a
X'T'. Objects of this type represent a time given in minutes. The
Xdifference to the standard numeric type is that when printed, these
Xminutes are always converted into hours and minutes. If you preceed
Xa time value with an 's', it is assumed to be in seconds rather than
Xminutes.
X
XSummary of field types:
X-------------------------------
XA text
XN numeric data
XT time in minutes or seconds
X-------------------------------
X
X1.4. fieldMultiplicity
X
XUsually every field within a record contains exactly one datum,
Xi.e. there is one title for a movie. Therefore the field multiplicity
Xwould be one, represented by 'O'.
X
XIn a movie there appear a number of actors. In order to 'simulate'
Xthis 1-to-N relation one field may contain any number of objects, as
Xlong as the field multiplicity is set to 'M' for multiple. If you
Xspecify a column with field multiplicity 'M' as the sort key, all the
Xentries in the field are used for sorting and the result is one line
Xin the report for every entry in the field. On the other hand if you
Xdon't use such a field for sorting you may specify how many of the
Xentered objects you want to see within the field. They then appear
Xconcatenated by a standard delimiter string.
X
XSometimes a field contains only a limited number of values. E.g. the
Xrecord mode in the video collection only takes the values SP for
X'short play' and LP for 'long play'. In this case the field
Xmultiplicity is 'S' for selection. The only difference to a standard
Xfield with multiple entries allows is that prg does a consistency
Xcheck of your input, i.e. if you supply a datum that's not within the
Xlist of possible selections it complains about it.
X
XFinally there are weightened selections. Suppose you have a number of
Xcategories that a movie more or less matches. You might want to give
Xyour personal marks to the movie with respect to this categories.
XHaving a field multiplicity type 'W' provides support for this.
XLike selections you specify all the categories you would like to
Xsee, but you also include information on how to abbreviate these
Xcategories. The definition for the 'Category' field in the video
Xdescription file looks like this:
X
XCAT#Categories#A#W#_C_omedy#_A_ction#_Science_Fiction#_T_hriller
X
XNote the underscore (_) characters in the category names. The
Xcharacters following the underscores are used to build the
Xabbreviations that appear in the column title later on, i.e.
Xthe title for the 'Categories' column looks like this:
XCo Ac SF Th
X
X
X---------------------------------------------------
XSummary of field multiplicity:
X---------------------------------------------------
XO only one entry allowed
XM multiple entries allowed
XS choice between a number of predefined values
XW a weight is assigned to a number of attributes
X---------------------------------------------------
X
XNote: Some combinations of field type and field multiplicity are not
Xsupported yet, i.e. a field of type 'T' is always supposed to have
Xmultiplicity one.
X
X------------------------------------------------------------------
X2. DATA FILE
X------------------------------------------------------------------
X
XThe data file contains an arbitrary number of records. Each record
Xmay define all the fields specified earlier in the description file.
XIf a field is not specified, it is considered empty for that record.
X
XThe beginning of a record is identified by an empty line. Each line up
Xto the next empty line is considered a definition line for this
Xrecord. Let's take a look at a record definition from the movie
Xcollection:
X
XNUM#2
XIDX#0
XDIR#John$McTiernan
XACT#Bruce$Willis#Alan$Rickman#Alexander$Godunov
XACT#Bonnie$Bedelia
XTIT#Die Hard
XLEN#125
XMOD#SP
XCAT#Ac3#Th2
X
XEach line starts with the field identifier followed by the field
Xseparator, the '#' character. Then comes the data for the field.
XFor simple fields like NUM, IDX or the title field this is just a
Xnumber or a string. If the field may contain more than one entry,
Xthese entries can be appended using even more '#' characters.
XTake a look at the definition of the actors in the above example,
Xwhere 4 actors are defined within two lines.
X
XOne important thing is the '$' character. It is used to determine
Xthe correct sorting order of the entry. Specifying
X
XACT#Bruce Willis
X
Xcreates an entry that, as far as sorting is concerned, starts with a 'B'.
X
XACT#Bruce$Willis
X
Xhowever results in the internal sort key 'Willis, Bruce', i.e. the
Xlast name comes first. This is very important when you enter names and
Xstuff like that as most often you will prefer the second behaviour to
Xthe first.
X
XThe second important thing is the specification of weightened selections.
XThe values you may assign to the attributes are restricted to the digits
X0 to 9. Thus you simply supply the abbreviation of the attribute followed
Xby the weight, as in
X
XCAT#Act3#Th2
X
Xwhich means that I consider the movie 'Die Hard' to have 3 Action and
X2 Thriller points.
X
XAs far as fields with type 'Time' are concerned: The time is always
Xgiven in minutes there, but the output shows the time in hours and
Xminutes.
X
XEND_OF_FILEINFO
X}
X
XInfoUsage()
X{
X cat << END_OF_USAGE
X
XUsage: prg input-file [ -format ID1#ID2#...#IDn ] [ -sortby ID1#ID2#..#IDn]
X [ -select [ YourSelectorFile | stdin ] ]
X [ -fontName YourPostScriptFontName ] [ -fontSize YourFontSize ]
X [ -unit faktor ]
X [ -title YourTitle ] [ -showTitle flag ] [ -delimiter delimiter ]
X [ -debug ] [ -debugExpr ] [ -debugPS ] [ -optimize flag ]
X [ -help ][ -libpath prglibpath ] [ -datapath prgdatapath ]
X [ -info anyOptionShownHere ]
X [ -info options ] [ -info guide ] [ -info files ]
X [ -info usage ] [ -caseCompare flag ] [ -landscape ]
X [ -noDuplicates ] [ -compareBySortCriteria flag ]
X [ -accuracy specifier ]
X
XEND_OF_USAGE
X}
X
XInfoOptions()
X{
X echo "------------------------------------------------------------------"
X echo "SUMMARY OF OPTIONS"
X echo "------------------------------------------------------------------"
X echo "Use '-info your-option' to get information about a specific option,"
X echo "e.g. '-info -format'"
X echo "------------------------------------------------------------------"
X
X InfoUsage
X InfoOption -format
X InfoOption -sortby
X InfoOption -select
X InfoOption -fontName
X InfoOption -unit
X InfoOption -title
X InfoOption -showTitle
X InfoOption -delimiter
X InfoOption -debug
X InfoOption -debugExpr
X InfoOption -debugPS
X InfoOption -optimize
X InfoOption -help
X InfoOption -libpath
X InfoOption -datapath
X InfoOption -info
X InfoOption -info options
X InfoOption -info guide
X InfoOption -info files
X InfoOption -usage
X InfoOption -caseCompare
X InfoOption -landscape
X InfoOption -noDuplicates
X}
X
XInfoOption()
X{
X echo
X echo -n "Information about the Option '"
X echo -n $*
X echo "' :"
X echo
X
X case $1 in
X -format | -f )
X cat << EO_FORMAT
XSelects the columns to be shown (in the given order)
XYou may specify the desired width of a column by
Xappending :WIDTH to the column name, where WIDTH
Xis always in centimeter, i.e. having a column called ACT
X
X-format ACT:5.5
X
Xwill result in the ACT column being exactly 5.5 cm wide.
X(The base unit can be changed using the '-unit' option).
X
XYou may also restrict the number of matches for multiple
Xfields, i.e. fields that may hold more than one entry:
X
X-format ACT-3
X
Xwould restrict the number of ACTs to be displayed to 3.
XBoth possibilities may be mixed.
XThe default is ${FORMAT}
XEO_FORMAT
X ;;
X -fontsize | -fs )
Xcat << EO_FONTSIZE
XFont size to be used (ignored when optimization is active).
XDefault is ${FONTSIZE}.
XEO_FONTSIZE
X ;;
X -delimiter | -delim )
Xecho "Defines the delimiter string for fields with multiple entries."
X ;;
X -sortby | -sort | -s )
Xcat << EO_SORTBY
XSelects the key columns to be used for sorting. If you preceed
Xthe key with a single dash (-), the sort is done in reverse order.
XDefault is ${SORTBY}
XEO_SORTBY
X ;;
X -select | -sel )
Xcat << EO_SELECT
XSupplied filename contains the selection string. As this string
Xcontains spaces it can't be passed on the command line.
XIf you specify 'stdin' as the filename, you will be prompted for
Xthe selector.
X
XExamples for selectors:
X
X(TIT == "Terminator") # selects all records where the TIT field
X # is Terminator
X
X(LEN > 120) # selects all movies longer than 2 hours
X
X(ACT == "Michael*") # all records with actors starting with Michael
X # NOTE: This expression is valid iff ACT is a
X # a sort key. Otherwise you would have to
X # use the contains-operator
X
XAll sequels of the Terminator series with Arnie:
X(ACT == "Arnold*") && (TIT=="Terminat*")
X
XAnd:
X
X(((ACT == Wil*) && (DIR contains Mc*)) || (NUM == 2))
X
XThis means: Select all entries where
Xa) the actor field (which has to be a sort key, otherwise == is not allowed!)
X contains a value starting with 'Wil' and the director field contains at least
X one value starting with 'Mc'
Xor
Xb) the NUM field has the value 2.
X
XEO_SELECT
X ;;
X -unit | -u )
Xcat << EO_UNIT
XMultiplier for the width parameter of the format string.
XDefaults to ${UNIT}, i.e. width is given in centimeter.
XIf you set the unit parameter to 1, the width is in points,
Xthe standard PostScript unit.
XEO_UNIT
X ;;
X -libpath | -lib )
Xcat << EO_LIB
XSpecifies the path where the AWK and SED programs
X(prg.awk and prg.sed) are located. Default is ${PRGLIBPATH}
XEO_LIB
X ;;
X -datapath | -data )
Xcat << EO_DATA
XSpecifies the path where the data files for prg are located.
XDefault is ${PRGDATAPATH}.
XEO_DATA
X ;;
X -title | -t )
X echo "Specify the title string of the report; default is \"${TITLE}\"."
X ;;
X -optimize | -opt )
Xcat << EO_OPTIMIZE
XBy default prg computes the width of the columns and the font
Xsize such that the fields you select in the format string fit
Xexactly into one line ouf the report. However, you might want
Xto adjust this settings manually. Specifying '-optimize 0' turns
Xthe optimization off completely. Note that you may also mix
Xoptimized size computation with your own specifications, as
Xany width information you supply in the format string always
Xoverrides the results from prg's own computation.
Xhave a default of '0' for the optimization, '-optimize 1'
Xturns optimization on again.
XEO_OPTIMIZE
X ;;
X -showTitle | -st )
X echo "Should a title page be drawn ?"
X echo "'-showTitle 1' enables the title page, '-showTitle 0' disables it."
X ;;
X -debug )
X echo "Print debugging information while processing the data."
X ;;
X -debugExpr | -de )
X echo "Enable debugging of the expression parser."
X ;;
X -debugPS | -dps )
X echo "Activate debugging within the PostScript file created."
X ;;
X -caseCompare | -case )
Xcat << EO_CASECOMPARE
XIf you specify '-caseCompare 1' sorting is done with respect to the
Xcase of the characters. Given '-caseCompare 0' sorting is case insensitive.
XEO_CASECOMPARE
X ;;
X -help | -h )
X echo "Displays some general notes about the program."
X ;;
X -info | -i )
X if [ $# -eq 1 ]
X then
X cat << EO_INFO_INFO
XThe option '-info' has to be followed by either one of
Xoptions, guide, files or usage, or any possible option
Xof prg, i.e.
X
Xprg -info -select
X
Xshows information about the '-select' parameter.
X
XEO_INFO_INFO
X else
X case $2 in
X options | o )
Xcat << EO_INFO_OPTIONS
XDisplays a list of prg's options and their meaning.
XEO_INFO_OPTIONS
X ;;
X guide | g )
Xcat << EO_INFO_GUIDE
XDisplays some notes on how to use the program, what can be
Xdone and how.
XEO_INFO_GUIDE
X ;;
X files | f )
Xcat << EO_INFO_FILES
XDisplays information about the structure of both the
Xdescription and data file.
XEO_INFO_FILES
X ;;
X * )
X echo "Display information about the option \"$2\", if it exists."
X ;;
X esac
X fi
X ;;
X -landscape | -l )
Xcat << EO_LANDSCAPE
XProduces pages in landscape format instead of the default
Xportrait format.
XEO_LANDSCAPE
X ;;
X -noDuplicates | -nd )
Xcat << EO_NODUPLS
XIf column 0 has the same value for row i and row i+1, the
Xvalue in the first column is not displayed in row i+1 if this flag
Xis given. Exception: The first line of a new page.
XEO_NODUPLS
X ;;
X -accuracy | -acc )
Xcat << EO_ACCURACY
XSpecifies the accuracy used when printing time data.
XPossible arguments are seconds, minutes or hours.
X '-accuracy seconds' displays any time field in the
Xformat HH:MM:SS, or, if the HH field is 'empty', as MM:SS.
XIf you specify '-accuracy minutes', the format is HH:MM.
XUsing '-accuracy hours' results in the 'HH' format.
XEO_ACCURACY
X ;;
X -compareBySortingCriteria | -cbsc )
Xcat << EO_CBSC
XOther name for this option: -compareBySortCriteria
XIf this flag is set with '-cbsc 1', comparison of strings
X(during the selection) is based on the entry as it is used
Xfor the sorting process, rather than the physical characters.
XI.e. given '-cbsc 1', the selector
X(ACT == H*)
Xwould match the entry Anthony$Hopkins, as this entry is modified
Xto 'Hopkins, Anthony' for sorting, which starts with an 'H'.
XUsing the option '-cbsc 0' it would be possible to match, for
Xexample, Harold$Ramis.
XEO_CBSC
X ;;
X esac
X echo
X}
X
XparseCommandLine()
X{
X for i
X do
X ANY=0
X if [ $XFORMAT -eq 1 ]; then FORMAT=$i; XFORMAT=0; ANY=1; fi
X if [ $XSORTBY -eq 1 ]; then SORTBY=$i; XSORTBY=0; ANY=1; fi
X if [ $XSELECT -eq 1 ]
X then
X if [ "$i" = "stdin" ]
X then
X echo "Please enter the expression you want me to use"
X echo -n "to select records from your data : "
X read SELECT
X XSELECT=0
X ANY=1
X else
X if [ -f $i ]
X then
X SELECT="`cat $i`"
X XSELECT=0
X ANY=1
X else
X echo
X echo The file \"$i\" which is supposed to hold the
X echo selector string could not be opened.
X echo
X exit
X fi
X fi
X fi
X if [ $XFONTNAME -eq 1 ]; then FONTNAME=$i; XFONTNAME=0; ANY=1; fi
X if [ $XFONTSIZE -eq 1 ]; then FONTSIZE=$i; XFONTSIZE=0; ANY=1; fi
X if [ $XDELIMITER -eq 1 ]; then DELIMITER="$i"; XDELIMITER=0; ANY=1; fi
X if [ $XTITLE -eq 1 ]; then TITLE="$i"; XTITLE=0; ANY=1; fi
X if [ $XACCURACY -eq 1 ]; then ACCURACY="$i"; XACCURACY=0; ANY=1; fi
X if [ $XUNIT -eq 1 ]; then UNIT=$i; XUNIT=0; ANY=1; fi
X if [ $XCASECOMP -eq 1 ]; then CASECOMP=$i; XCASECOMP=0; ANY=1; fi
X if [ $XSHOWTITLE -eq 1 ]
X then
X if [ $i -eq 1 ]
X then
X SHOWTITLE="true"
X else
X SHOWTITLE="false"
X fi
X XSHOWTITLE=0
X ANY=1
X fi
X if [ $XCBSC -eq 1 ]; then CBSC=$i; XCBSC=0; ANY=1; fi
X if [ $XOPTIMIZE -eq 1 ]
X then
X if [ $i -eq 1 ]
X then
X OPTIMIZE="true"
X else
X OPTIMIZE="false"
X fi
X XOPTIMIZE=0
X ANY=1
X fi
X if [ $XINFO -eq 1 ]
X then
X XINFO=0
X case $i in
X guide | g )
X InfoGuide
X exit
X ;;
X usage | u )
X InfoUsage
X exit
X ;;
X options | o )
X InfoOptions
X exit
X ;;
X files | f )
X InfoFiles
X exit
X ;;
X * )
X InfoOption $i
X exit
X ;;
X esac
X fi
X if [ $XLIBPATH -eq 1 ]; then PRGLIBPATH=$i; XLIBPATH=0; ANY=1; fi
X if [ $XDATAPATH -eq 1 ]
X then
X PRGDATAPATH=$i
X INFILE=${PRGDATAPATH}/`basename ${INFILE}`
X DESFILE=${INFILE}.des
X XDATAPATH=0
X ANY=1
X fi
X
X case $i in
X -format | -f )
X XFORMAT=1;ANY=1
X ;;
X -fontsize | -fs )
X XFONTSIZE=1;ANY=1
X ;;
X -delimiter | -delim )
X XDELIMITER=1;ANY=1
X ;;
X -sortby | -sort | -s )
X XSORTBY=1;ANY=1
X ;;
X -select | -sel )
X XSELECT=1;ANY=1
X ;;
X -unit | -u )
X XUNIT=1;ANY=1
X ;;
X -libpath | -lib )
X XLIBPATH=1;ANY=1
X ;;
X -datapath | -data )
X XDATAPATH=1; ANY=1
X ;;
X -title | -t )
X XTITLE=1;ANY=1
X ;;
X -optimize | -opt )
X XOPTIMIZE=1;ANY=1
X ;;
X -showTitle | -st )
X XSHOWTITLE=1;ANY=1
X ;;
X -debug )
X DEBUG=1;ANY=1
X ;;
X -debugExpr | -de )
X DEBUGEXPR=1;ANY=1
X ;;
X -debug )
X DEBUG=1;ANY=1
X ;;
X -debugPS | -dps )
X DEBUG_PS="true";ANY=1
X ;;
X -caseCompare | -case )
X XCASECOMP=1;ANY=1
X ;;
X -help | -h )
X Help
X exit
X ;;
X -info | -i )
X XINFO=1;ANY=1
X ;;
X -landscape | -l )
X LANDSCAPE="true";ANY=1
X ;;
X -keeptemp | -k )
X KEEPTEMP=1;ANY=1
X ;;
X -noDuplicates | -nd )
X NODUPLS="true";ANY=1
X ;;
X -accuracy | -acc )
X XACCURACY=1;ANY=1
X ;;
X -compareBySortingCriteria | -cbsc )
X XCBSC=1;ANY=1
X ;;
X esac
X
X if [ $ANY -eq 0 ]
X then
X if [ $INFILESET -eq 1 ]
X then
X echo Input file has already been set to $INFILE
X echo
X InfoUsage
X exit
X fi
X INFILESET=1
X INFILE=${PRGDATAPATH}/$i
X DESFILE=${INFILE}.des
X TIFILE=`echo $i | sed 's/^-//g'`
X if [ "$i" != "$TIFILE" ]
X then
X echo I guess you supplied an unknown parameter \"$i\"
X echo
X InfoUsage
X exit
X fi
X fi
X
X done
X}
X
XinitVariables()
X{
X COMLINE="$*"
X # initizialize temporary variables
X XFORMAT=0
X XSORTBY=0
X XSELECT=0
X XFONTNAME=0
X XFONTSIZE=0
X XDELIMITER=0
X XOPTIMIZE=0
X XSHOWTITLE=0
X XCBSC=0
X XTITLE=0
X XACCURACY=0
X XUNIT=0
X XCASECOMP=0
X XINFO=0
X XLIBPATH=0
X XDATAPATH=0
X INFILESET=0
X # keep temporary files ?
X KEEPTEMP=0
X # temporary files
X SORTFILENAME=${TMPDIR}/sort.sh
X TMPDATA=${TMPDIR}/data.tmp
X TMPHEADER=${TMPDIR}/header.tmp
X}
X
XcheckDataFiles()
X{
X if [ ! -f $INFILE ]
X then
X doexit=1
X echo The input file \"$INFILE\" does not exist.
X if [ $INFILE != `basename ${INFILE}` ]
X then
X INFILE=`basename $INFILE`
X echo Trying the file $INFILE instead.
X if [ ! -f $INFILE ]
X then
X echo The input file \"$INFILE\" does not exist.
X else
X echo "Ok, I'll use the file ${INFILE}."
X doexit=0
X DESFILE=${INFILE}.des
X fi
X fi
X if [ $doexit -eq 1 ]
X then
X exit
X fi
X fi
X
X if [ ! -f $DESFILE ]
X then
X echo Die Beschreibungsdatei \"$DESFILE\" zur Eingabedatei \"$INFILE\" existiert nicht.
X exit
X fi
X
X /bin/rm -f $TMPDATA $TMPHEADER
X
X echo > $TMPHEADER
X echo "% HEADER ----------------------------------------------------------------" >> $TMPHEADER
X echo >> $TMPHEADER
X}
X
XcreatePostScriptFile()
X{
Xcat << END_OF_PS_HEADER > $PSFILE
X%!
X%%Creator: $USER on `hostname` using prg
X%%Title: ${TITLE}
X%%CreationDate: `date`
X%%DocumentFonts: ${FONTNAME}
X%%EndComments
X
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X% %
X% prg - patsch's PostScript report generator Release 1.1 %
X% %
X% Copyright (C) 1994 Patrick Dockhorn %
X% Permission to use and modify this software and its %
X% documentation for any purpose other than its incorporation %
X% into a commercial product is hereby granted without fee. %
X% Permission to copy and distribute this software and its %
X% documentation only for non-commercial use is also granted %
X% without fee, provided, however, that the above copyright %
X% notice appear in all copies, that both that copyright %
X% notice and this permission notice appear in supporting %
X% documentation. The author makes no representations about %
X% the suitability of this software for any purpose. It is %
X% provided \`\`as is'' without express or implied warranty. %
X% %
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X
X%%EndProlog
X
X% recode font vector to enable foreign special characters
X% copied from PostScript cookbook
X
X/reencsmalldict 12 dict def
X/ReEncodeSmall
X{
X reencsmalldict begin
X /newcodesandnames exch def
X /newfontname exch def
X /basefontname exch def
X
X /basefontdict basefontname findfont def
X /newfont basefontdict maxlength dict def
X
X basefontdict
X {
X exch dup /FID ne
X {
X dup /Encoding eq
X { exch dup length array copy
X newfont 3 1 roll put }
X { exch newfont 3 1 roll put }
X ifelse
X }
X { pop pop }
X ifelse
X } forall
X
X newfont /FontName newfontname put
X newcodesandnames aload pop
X newcodesandnames length 2 idiv
X { newfont /Encoding get 3 1 roll put } repeat
X newfontname newfont definefont pop
X end
X} def
X
X% ------------------------------------------------------------------
X%
X% germanvec is an array that contains positions and character
X% names. The given characters, - they are usually not included
X% in the standard font encoding - are activated at the given
X% positions in the character set.
X% To use your own characters (i.e. /ccedilla, modify
X% the font vector accordingly.
X% The PostScript Language Reference contains the names
X% of characters available as well as a map of unused
X% regions in the standard text encoding.
X% The following octal regions can be used in a standard
X% text encoding without removing other characters:
X% \260, \300, \321-\341, \354-\360, \362-\364, \366-\367, \374-\376
X%
X% ------------------------------------------------------------------
X
X/germanvec [
X 8#300 /adieresis
X 8#311 /Adieresis
X 8#321 /odieresis
X 8#322 /Odieresis
X 8#323 /udieresis
X 8#324 /Udieresis
X 8#325 /germandbls
X 8#326 /eacute
X 8#327 /egrave
X 8#330 /ecircumflex
X 8#331 /ccedilla
X 8#332 /otilde
X 8#333 /atilde
X 8#334 /ntilde
X 8#335 /copyright
X 8#336 /registered
X 8#337 /trademark
X 8#340 /Ccedilla
X 8#341 /aacute
X] def
X
X% ------------------------------------------------------------------
X%
X% - Umlaute -
X%
X% Activate the new font encoding that includes foreign umlauts
X% for the font selected by the user by FONTNAME.
X%
X% ------------------------------------------------------------------
X
X/Umlaute
X{
X /${FONTNAME} /GermanFont germanvec ReEncodeSmall
X} def
X
X% ------------------------------------------------------------------
X%
X% (text) width clipshow -
X%
X% The given text is shown at the current point. Before the text
X% is displayed, a clip rectangle is placed around it with the
X% given width. This avoids overlapping text in adjacent columns.
X%
X% ------------------------------------------------------------------
X
X/clipshow
X{
X gsave
X newpath x0 1 add y0 1 add moveto 2 sub dup 0 rlineto
X 0 lsize 2 sub rlineto neg 0 rlineto closepath clip
X newpath x0 xboff add y0 descent add yboff add moveto show
X grestore
X} def
X
X% ------------------------------------------------------------------
X%
X% prg-array optimizeColumns -
X%
X% optimizeColumns uses the given array of application specific data
X% to update its internal state as far as the maximum column width
X% required is concerned.
X%
X% ------------------------------------------------------------------
X
X/optimizeColumns
X{
X % --------------------------------------------------------------------------
X % use all the information given to compute optimal column widths & font size
X % --------------------------------------------------------------------------
X {
X /elem exch def % define current element
X % (elem is) == elem ==
X 0 1 nColumns 1 sub % loop through all columns
X {
X /i exch def
X fieldMulti i get (W) eq
X {
X % Weightened Selection: Column Width is constant, i.e.
X % compute only once
X maxSizes i get 0 eq % not yet computed -> do it
X {
X /legend true def
X /len 0 def
X multiWeightSelTitles i get
X {
X stringwidth pop multiOff dup add add len add /len exch def
X } forall % for all strings in the multi weight info array
X % put information about the size of the field into the array
X maxSizes i len put
X } if
X } % end if current column is weightened selection
X { % if current column is NOT a weightened selection
X % simply compute the width of the given strings using
X % their maximum multiplicity as given in /colMultiplicity
X % the strings are concatenated using the delimiter string
X /cnt 0 def % counter for maximum multiplicity
X /len xboff dup add def
X /maxMultiplicity colMultiplicity i get def
X elem i get
X dup /nMultis exch length def
X {
X /len exch stringwidth pop len add
X % should I append the delimiter ?
X /cnt cnt 1 add def
X cnt nMultis ne
X cnt maxMultiplicity ne and
X {
X delimiter stringwidth pop add def
X }
X {
X def exit
X } ifelse
X } forall
X % if size exceeds maximum, store it
X maxSizes i get len lt
X {
X maxSizes i len put
X } if
X } ifelse % end if current column is *not* a weightened selection
X } for % for all selected columns
X } forall % end optimization loop through the input array
X} def
X
X% ------------------------------------------------------------------
X%
X% - postOptimization -
X%
X% Uses the information obtained from calling optimizeColumns
X% (several times, if the input data is too large)
X% and mixes it with field widths given by the user to compute
X% the new font size and applies the resulting scaling factor
X% to a number of internal parameters.
X%
X% ------------------------------------------------------------------
X
X/postOptimization
X{
X 0 1 nColumns 1 sub
X {
X /i exch def
X colSizes i get -1 eq % no size given -> use the computed size
X {
X colSizes i maxSizes i get put
X debug
X {
X (\012 Computed width for column ') print colNames i get print
X (' to ) print colSizes i get 12 string cvs print
X } if
X }
X {
X debug
X {
X (\012 Using specified width \() print colSizes i get
X 12 string cvs print ( points\) for column ') print
X colNames i get print
X } if
X } ifelse
X } for
X 0 colSizes { add } forall
X /total exch def
X /factor hspace total div def % scaling factor
X /fsize fsize factor mul def
X /GermanFont findfont fsize scalefont setfont
X % update column size information
X [ colSizes { factor mul } forall ] /colSizes exch def
X /multiOff multiOff factor mul def
X
X /sbbox 4 array def %% compute scaled bounding box
X 0 1 3
X {
X /i exch def
X sbbox i bbox i get fsize mul 1000 div put
X } for
X
X % size of one line, taking descent and font size into account
X /lsize sbbox 3 get sbbox 1 get
X sub yboff dup add add def
X
X % current descent value, used to position the characters vertically
X % within a line
X /descent sbbox 1 get neg def %% 0 is origin, lly is therefore negative descent
X
X debug { (\012 Descent set to ) print descent 10 string cvs print (\012) print } if
X /nLines vspace lsize div cvi def %% number of lines on one page according to line size
X
X % update available vertical space
X /vspace nLines lsize mul def
X
X % compute expected number of pages
X totalEntries nLines 1 sub idiv totalEntries nLines 1 sub mod 0 ne { 1 add } if
X /nPages exch def
X /nPagesStr nPages 10 string cvs def
X
X debug { (\012 Report will consist of ) print nLines 10 string cvs print ( lines per page.) print } if
X debug { (\012 Optimization finished, using font size ) print fsize 10 string cvs print } if
X
X % ------------------------------------------------------------------
X % print title page
X % ------------------------------------------------------------------
X
X showtitle
X {
X 16 dict begin
X top
X newpath
X gsave
X 0 0 moveto title true charpath pathbbox
X /tury exch def
X /turx exch def
X /tlly exch def
X /tllx exch def
X % the '18 sub' is to leave some space at the border for
X % additional infos
X newpath hspace 18 sub turx tllx sub div /sfak exch def
X hspace 2 div vspace 2 div translate sfak sfak scale
X tllx turx sub 2 div tlly tury sub 2 div moveto title show
X grestore
X % compute positions required for user name and sorting criteria
X % debug { (\012 size of title string is ) print turx tllx sub 10 string cvs print } if
X % debug { (\012 scaling factor is ) print sfak 10 string cvs print } if
X /topoff vspace tury tlly sub sfak mul add 2 div yboff add lsize add def
X /botoff sortFields length lsize mul def
X userstr stringwidth pop ( presents) stringwidth pop add neg hspace add 2 div
X topoff moveto userstr show ( presents) show
X % display the sort keys
X (Sorting Criteria:) stringwidth pop neg hspace add 2 div /scx exch def
X scx botoff moveto (Sorting Criteria:) show
X sortFields
X {
X /botoff botoff lsize sub def
X scx botoff moveto show
X } forall
X % show date and page info
X 0 vspace lsize sub moveto datestr show
X hspace timestr stringwidth pop sub vspace lsize sub moveto timestr show
X 0 0 moveto totalEntries 16 string cvs show ( lines) show
X % display total number of pages
X hspace ( pages) stringwidth pop sub
X nPagesStr stringwidth pop sub 0 moveto
X nPagesStr show ( pages) show
X gsave
X /GermanFont findfont 6 scalefont setfont
X gsave
X 0 vspace 2 div translate 90 rotate
X commandLine dup stringwidth pop 2 div neg 0
X moveto show
X grestore
X gsave
X hspace vspace 2 div translate -90 rotate
X (thanks for using patsch's PostScript Report Generator - (C) 1994 Patrick Dockhorn)
X dup stringwidth pop 2 div neg 0
X moveto show
X grestore
X grestore
X end
X showpage
X } if
X
X % ------------------------------------------------------------------
X % print legend if any weightened selection present
X % ------------------------------------------------------------------
X
X legend
X {
X 12 dict begin
X top
X /y0 vspace lsize sub def
X newpath (Additional Information) dup
X stringwidth pop neg
X dup /tmpsw exch def
X hspace add 2 div y0 moveto show
X tmpsw 0 rlineto stroke
X /y0 y0 lsize dup add sub def
X /nhits 0 def
X 0 1 nColumns 1 sub
X {
X /i exch def
X fieldMulti i get (W) eq
X {
X /ybuf y0 def
X /nhits nhits 1 add def
X nhits 2 mod 0 eq
X {
X /x0 hspace 2 div xboff add def
X }
X {
X /x0 xboff def
X } ifelse
X newpath x0 y0 moveto (Explanation for column ') show
X colNames i get show (' :) show
X x0 y0 lineto stroke newpath
X /mss 0 def
X /scarr multiWeightSelTitles i get def
X /ltarr multiWeightSelFullTitles i get def
X scarr
X {
X stringwidth pop dup mss gt { /mss exch def } { pop } ifelse
X } forall
X
X 0 1 scarr length 1 sub
X {
X /j exch def
X /y0 y0 lsize sub def
X x0 y0 moveto scarr j get show
X x0 mss add xboff dup add add y0 moveto ltarr j get show
X } for
X nhits 2 mod 0 eq
X {
X /y0 y0 lsize dup add sub def
X }
X {
X /y0 ybuf def
X } ifelse
X } if
X } for
X showpage
X end
X } if
X} def
X
X
X% ------------------------------------------------------------------
X%
X% prg-array createReport -
X%
X% Prints the data given in prg-array (which is in a format specified
X% through the -format option) nicely formatted. Does all the pagebreak,
X% handling, rotation etc.
X%
X% ------------------------------------------------------------------
X
X/createReport
X{
X % ------------------------------------------------------------------
X % handle all array elements
X % ------------------------------------------------------------------
X
X {
X /elem exch def % define current element
X line 0 eq % Top of page ?
X {
X top
X /x0 0 def
X /y0 vspace def % start value for y
X 0 setlinewidth % set line width for bounding box
X newpath 0 0 moveto hspace 0 rlineto 0 vspace rlineto
X hspace neg 0 rlineto closepath
X /y0 y0 lsize sub def
X 0 y0 moveto hspace 0 rlineto stroke
X
X gsave
X /GermanFont findfont 6 scalefont setfont
X newpath 0 vspace yboff add moveto title show delimiter show datestr show
X newpath hspace (Page ) stringwidth pop sub page 1 add 10 string cvs /pagestr exch def
X pagestr stringwidth pop sub ( / ) stringwidth pop sub nPagesStr stringwidth pop sub
X vspace yboff add moveto (Page ) show pagestr show ( / ) show nPagesStr show
X grestore
X
X 0 1 nColumns 1 sub
X {
X /i exch def
X /cs colSizes i get def
X debug
X {
X (\012 Column size for ') print colNames i get print (' is ) print
X cs 10 string cvs print (\012) print
X } if
X
X fieldMulti i get (W) eq % multi-field -> special title
X {
X /xbuf x0 def
X /j 0 def
X /offArr colMultiOffsets i get def
X % debug { (\012 offArr for column ) print colNames i get print ( is \012) print offArr == } if
X /mwsl multiWeightSelTitles i get length def
X multiWeightSelTitles i get
X {
X dup stringwidth pop /mssize exch def % save string size
X newpath x0 multiOff add y0 yboff add descent add moveto % position
X show
X offArr j x0 put % save current x position
X j 0 gt j mwsl ne and
X {
X x0 y0 lsize add moveto 0 vspace neg
X rlineto stroke
X } if
X /j j 1 add def
X mssize multiOff dup add add
X dup x0 add /x0 exch def
X neg cs add /cs exch def
X } forall
X /x0 xbuf def
X
X% debug
X% {
X% (\012 Updated colMultiOffsets[) print i 10 string cvs print
X% (] to the following offset array:\012) print offArr ==
X% } if
X
X colMultiOffsets i offArr put
X }
X {
X colNames i get cs clipshow
X } ifelse
X i 0 gt { newpath x0 y0 lsize add moveto 0 vspace neg rlineto stroke } if
X /x0 x0 colSizes i get add def
X } for % end for all columns
X debug { (\012 Multi-Column offset array:\012) print colMultiOffsets == } if
X
X /y0 y0 lsize sub def
X } if % end if first line of page
X
X %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X %
X % Standard Procedure for a single entry
X %
X %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X
X newpath
X /x0 0 def
X 0 1 nColumns 1 sub
X {
X /i exch def
X fieldMulti i get (W) eq % Weightened selection
X {
X /done false def
X % debug { (\012 Handling multi field ') print colNames i get print ('\012) print } if
X elem i get
X {
X % debug { (\012 Checking weightened selection ) print dup == } if
X dup 1 get /val exch def
X 0 get /cat exch def
X % search for the position of the category
X /idx 0 def
X multiWeightSelTitles i get
X {
X cat eq % category match -> show the corr. value
X {
X colMultiOffsets i get idx get multiOff add
X cat stringwidth pop add val stringwidth pop sub
X y0 yboff add descent add moveto val show
X /done true def
X exit
X } if
X /idx idx 1 add def
X } forall
X done { exit } if
X } forall
X } % end if current column is weightened selection
X { % if current column is NOT a weightened selection
X % simply compute the width of the given strings using
X % their maximum multiplicity as given in /colMultiplicity
X % the strings are concatenated using the delimiter string
X
X % first check if the current element is the same
X % as the previous one, if so, and duplicate elim.
X % is selected, nothing is displayed
X % (except if this is the first line of a new page)
X
X /displayThis true def
X noDupls line 0 ne and i 0 eq and
X {
X /tidx 0 def
X true
X elem i get
X {
X lastElem i get tidx get eq and
X /tidx tidx 1 add def
X } forall
X not /displayThis exch def
X } if
X
X displayThis
X {
X line 0 ne i 0 eq and
X {
X 0 y0 lsize add yboff add moveto hspace 0 rlineto stroke
X } if
X /cnt 0 def % counter for maximum multiplicity
X /xwidth colSizes i get def
X /maxMultiplicity colMultiplicity i get def
X /xbuf x0 def
X elem i get
X dup /nMultis exch length def
X nMultis 1 eq
X {
X % only one entry -> check for the field type and
X % display numeric values right justified
X
X
X 0 get
X fieldTypes i get dup (N) eq exch (T) eq or
X {
X dup stringwidth pop neg x0 add xwidth add
X xboff dup add sub
X /x0 exch def xwidth clipshow
X }
X {
X % no numeric field
X xwidth clipshow
X } ifelse
X }
X {
X % more than one entry
X {
X dup
X xwidth clipshow
X stringwidth pop dup neg xwidth add /xwidth exch def
X x0 add /x0 exch def
X % should I append the delimiter ?
X /cnt cnt 1 add def
X cnt nMultis ne
X cnt maxMultiplicity ne and
X {
X delimiter xwidth clipshow
X delimiter stringwidth pop dup
X x0 add /x0 exch def neg xwidth add
X /xwidth exch def
X }
X {
X exit % leave if maximum multiplicity reached
X } ifelse
X } forall
X } ifelse
X /x0 xbuf def
X } if % if entry should be shown at all
X } ifelse % end if not a weightened selection
X
X /x0 x0 colSizes i get add def
X
X } for % end for all columns
X
X % one line is finished
X % debug { (\012 Line ) print line 10 string cvs print ( printed.) print } if
X
X /line line 0 eq
X { line 2 add } { line 1 add } ifelse
X dup nLines ge { pop 0 /page page 1 add def showpage } if def
X /y0 y0 lsize sub def % new y starting position
X /lastElem elem def % remember last element for duplicate elimination
X } forall % end for all data
X} def
X
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X%%
X%% M M A III N N
X%% MM MM A A I NN N
X%% M M M M A A I N N N
X%% M M M A A I N N N
X%% M M AAAAAAA I N N N
X%% M M A A I N NN
X%% M M A A III N N
X%%
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X
X128 dict begin % start a large user dictionary
X
XUmlaute % activate german (or, more generally, foreign Umlauts)
X
X/GermanFont findfont $FONTSIZE scalefont setfont % select font
X
X% Dynamic data for output header
X
X/cm { 28.346456 mul } def %% definition of a cm based in points
X/pageWidth ${PAGEWIDTH} def %% Width of a page
X/pageHeight ${PAGEHEIGHT} def %% Height of a page
X/hoff ${HOFF} def %% horizontal skip value
X/voff ${VOFF} def %% vertical skip value
X
X/landscape ${LANDSCAPE} def %% Print in landscape mode ?
X/datestr (`date +%d.%m.%y`) def %% today's date
X/timestr (`date +%H:%M:%S`) def %% current time
X/userstr (${USER}) def %% user running the program
X/fsize $FONTSIZE def %% base font used
X/title (${TITLE}) def %% title for the report
X/delimiter (${DELIMITER}) def %% delimiter string for multi-fields
X/noDupls ${NODUPLS} def %% display values if same for two succeeding rows ?
X
X% define size variables depending on landscape parameter
X
Xlandscape
X{
X /lph pageWidth def
X /lpw pageHeight def
X}
X{
X /lpw pageWidth def
X /lph pageHeight def
X} ifelse
X
X% procedure called when new page is started
X
X/top
X{
X landscape
X {
X -90 rotate pageHeight neg 0 translate
X } if
X hoff voff translate
X} def
X
X
X%% ------------------------------------------------------------------
X%% the following arrays were created by the prg.awk program
X%% ------------------------------------------------------------------
X
XEND_OF_PS_HEADER
X
Xcat $TMPHEADER | sed -f ${PRGLIBPATH}/prg.sed >> $PSFILE
X
Xcat << END_OF_PS_HEAD3 >> $PSFILE
X
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X%% define global variables used for optimization
X%% and printing
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X
X/optimize ${OPTIMIZE} def %% optimize output size ?
X/debug ${DEBUG_PS} def %% PostScript debugging
X/showtitle ${SHOWTITLE} def %% display title page ?
X/commandLine (command line used: ${COMLINE}) def %% how the program was invoked
X/line 0 def %% current line
X/page 0 def %% current page
X/hspace lpw hoff dup add sub def %% space available horizontally
X/vspace lph voff dup add sub def %% space available vertically
X/xboff 3 def %% box offset horizontally
X/yboff 2 def %% box offset horizontally
X/multiOff 2 def %% Offset for multiple weightened selection
X/x0 0 def %% start value for x
X
X/nColumns colSizes length def %% number of columns
X/bbox /GermanFont findfont
X/FontBBox get [ exch aload pop ] def %% Bounding-Box (scale-independent)
X/legend false def %% draw a legend on the second page ?
X/maxSizes nColumns array def %% array to hold the maximum values
X
X0 1 nColumns 1 sub %% NULL the maxSizes array
X{
X maxSizes exch 0 put
X} for
X
X%% compute default values for column widths if no optimization requested
X
Xoptimize not
X{
X % compute default sizes for the columns (if no explicit data given)
X 0 1 nColumns 1 sub
X {
X /i exch def colSizes i colSizes i get
X dup -1 eq { pop hspace nColumns div } if put
X fieldMulti i get (W) eq { /legend true def } if
X } for
X} if % no optimization -> compute default values
X
X% ------------------------------------------------------------------
X% ------------------------------ DATA ------------------------------
X% ------------------------------------------------------------------
X
XEND_OF_PS_HEAD3
X
X
X# Determine the split factor for the input data, i.e. how often it has to
X# be split in order to avoid a memory overflow in the printer
X
XTMPPFIX=${TMPDIR}/split`date +%S%M`
X
Xif [ $NELEMENTS -gt $MAXARRAYSIZE ]
Xthen
X /bin/rm -f ${TMPPFIX}* 1>/dev/null 2>/dev/null
X cat ${TMPDATA} | split -l $MAXARRAYSIZE -a 4 - ${TMPPFIX}
X TMPCNT=1
X CNTMAX=0
X for fi in `ls ${TMPPFIX}*`
X do
X CNTMAX=`expr $CNTMAX + 1`
X done
X echo -n "Creating PostScript report"
X if [ "$OPTIMIZE" = "true" ]
X then
X cat << END_OF_PSHEAD1 >> $PSFILE
X
X
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X%%
X%% Pass 1 : Computing optimized column widths
X%%
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X
XEND_OF_PSHEAD1
X
X fi
X
X # Pass 1 : Optimization
X
X for fi in `ls ${TMPPFIX}*`
X do
X echo -n "."
X echo "" >> $PSFILE
X if [ "$OPTIMIZE" = "true" ]
X then
X echo -n "%% Pass 1, " >> $PSFILE
X else
X echo -n "%% " >> $PSFILE
X fi
X echo -n "Part ${TMPCNT} / ${CNTMAX} from `basename $INFILE`" >> $PSFILE
X echo " (`cat $fi | wc -l | sed 's/[ ]*//g'` elements)" >> $PSFILE
X echo "[" >> $PSFILE
X cat $fi >> $PSFILE
X if [ "$OPTIMIZE" = "true" ]
X then
X echo "] optimizeColumns %% use data to compute optimal column widths (Pass 1)" >> $PSFILE
X else
X echo "] postOptimization createReport %% print the data using the default settings" >> $PSFILE
X fi
X TMPCNT=`expr $TMPCNT + 1`
X done
X
X # Pass 2 : Printing
X
X if [ "$OPTIMIZE" = "true" ]
X then
X cat << END_OF_PSHEAD2 >> $PSFILE
X
X% post-process optimization, create title page and legend
X
XpostOptimization
X
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X%%
X%% Pass 2 : Create the report and print it out
X%%
X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
X
XEND_OF_PSHEAD2
X
X TMPCNT=1
X for fi in `ls ${TMPPFIX}*`
X do
X echo -n "."
X echo "" >> $PSFILE
X echo -n "%% Pass 2, Part ${TMPCNT} / ${CNTMAX} from `basename $INFILE`" >> $PSFILE
X echo " (`cat $fi | wc -l | sed 's/[ ]*//g'` elements)" >> $PSFILE
X echo "[" >> $PSFILE
X cat $fi >> $PSFILE
X echo "] createReport %% print the data using the precomputed settings" >> $PSFILE
X TMPCNT=`expr $TMPCNT + 1`
X /bin/rm -f $fi
X done
X fi # end if optimization requested
X
X echo "done" # splitting finished
X
Xelse
X echo -n "Creating PostScript report..."
X # input does not have to be splitted, i.e. small amount of data
X echo "[" >> $PSFILE
X cat ${TMPDATA} >> $PSFILE
X echo -n "] " >> $PSFILE
X if [ "$OPTIMIZE" = "true" ]
X then
X echo -n "dup optimizeColumns " >> $PSFILE
X fi
X echo "postOptimization createReport" >> $PSFILE
X echo "done."
Xfi
Xecho "line 0 eq not { showpage } if" >> $PSFILE
Xecho "end % end large user dictionary" >> $PSFILE
Xecho "%%TRAILER" >> $PSFILE
Xecho >> $PSFILE
X
X}
X
X##################################################################
X##################################################################
X#
X# MAIN ('mainprg') - patsch's PostScript report generator
X#
X##################################################################
X##################################################################
X
X
XinitVariables $0 $* # initialize temporary variables
XparseCommandLine $* # parse the command line
XcheckDataFiles # check whether the data files exist
X
X
X#######################################################
X#
X# 1. Create an array of data suitable as input to the
X# postscript functions.
X#
X#######################################################
X
X# Selection step may be added later
X
Xecho -n "Selecting records from $INFILE "
X
Xcat $DESFILE $INFILE | $AWK -v FS='#' -v debug=$DEBUG \
X -v debugExpr=$DEBUGEXPR \
X -v tmpData=$TMPDATA \
X -v fn=$FONTNAME \
X -v fsize=$FONTSIZE \
X -v format=$FORMAT \
X -v sortby=$SORTBY \
X -v select="$SELECT" \
X -v tmpHeader=$TMPHEADER \
X -v sortFileName=$SORTFILENAME \
X -v unit=$UNIT \
X -v casecomp=$CASECOMP \
X -v accuracy=$ACCURACY \
X -v compareLastNames=$CBSC \
X -f ${PRGLIBPATH}/prg.awk
X
X
Xif [ $? -ne 0 ]
Xthen
X echo
X echo ${PRGLIBPATH}/prg.awk produced an error.
X echo Please check any previous error output and fix
X echo the problems mentioned - bailing out.
X exit
Xfi
Xecho done.
X
XNELEMENTS=`cat ${TMPDATA} | wc -l`
Xecho -n Sorting $NELEMENTS records...
X
X#######################################################
X#
X# 2. Strip off trailing blanks in the postscript
X# strings and sort the data according to the keys.
X#
X#######################################################
X
Xchmod +x $SORTFILENAME
X./$SORTFILENAME ${TMPDATA}
Xecho done
X
X# strip off leading sort keys, convert umlauts and strip
X# away trailing blanks in strings
X
XNSORTFIELDS=`cat ${TMPHEADER}.nsf`
Xcat ${TMPDATA}.srt | cut -d '#' -f${NSORTFIELDS}- | sed -f ${PRGLIBPATH}/prg.sed > ${TMPDATA}
X
X#######################################################
X#
X# 3. Create the PostScript file
X#
X#######################################################
X
XPSFILE=`basename ${INFILE}`.ps
X
XcreatePostScriptFile
X
Xecho
Xecho Your report was written into the file ${PSFILE}.
Xecho You may want to print it out using the standard
Xecho "printer command (usually lpr on UNIX machines)."
Xecho
Xecho "Thanks for using patsch's PostScript report generator."
X
Xif [ $KEEPTEMP -eq 0 ]
Xthen
X # remove temporary data
X /bin/rm -f ${TMPHEADER} ${TMPHEADER}.nsf ${TMPDATA} ${TMPDATA}.srt ${SORTFILENAME}
Xfi
END_OF_FILE
if test 70190 -ne `wc -c <'prg/prg'`; then
echo shar: \"'prg/prg'\" unpacked with wrong size!
fi
chmod +x 'prg/prg'
# end of 'prg/prg'
fi
echo shar: End of archive 1 \(of 6\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 6 archives.
rm -f ark[1-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...