home *** CD-ROM | disk | FTP | other *** search
- 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...
-