home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume43 / prg / part05 < prev    next >
Encoding:
Internet Message Format  |  1994-06-10  |  67.2 KB

  1. From: patsch@ubka.uni-karlsruhe.de (Patrick Dockhorn)
  2. Newsgroups: comp.sources.misc
  3. Subject: v43i036:  prg - PostScript report generator V1.1, Part05/06
  4. Date: 10 Jun 1994 10:22:52 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <2ta0gc$7b6@sparky.sterling.com>
  9. X-Md4-Signature: 96a86d1ab8814f522e3359ce6e0a8e6f
  10.  
  11. Submitted-by: patsch@ubka.uni-karlsruhe.de (Patrick Dockhorn)
  12. Posting-number: Volume 43, Issue 36
  13. Archive-name: prg/part05
  14. Environment: postscript, UNIX
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  prg/INSTALL prg/README
  21. #   prg/doc/videos-by-actors-first-name-starts-A-or-B.ps
  22. #   prg/lib/prg.awk prg/lib/prg.sed.UU
  23. # Wrapped by kent@sparky on Thu Jun  9 12:32:34 1994
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 5 (of 6)."'
  27. if test -f 'prg/INSTALL' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'prg/INSTALL'\"
  29. else
  30.   echo shar: Extracting \"'prg/INSTALL'\" \(1173 characters\)
  31.   sed "s/^X//" >'prg/INSTALL' <<'END_OF_FILE'
  32. X------------------------------------------
  33. XPostScript report generator - INSTALLATION
  34. X------------------------------------------
  35. X
  36. XIf you got the package from USENET News skip steps
  37. X1 to 3; they are required only if you got a gzip'ed
  38. Xtar file from our ftp server.
  39. X
  40. X1. copy the file prg.tar.gz into a local subdirectory
  41. X   of yours - you need write permission there in order
  42. X   to unpack the file.
  43. X2. uncompress the file with the command 'gunzip prg.tar.gz'
  44. X3. untar the file with the command 'tar xf prg.tar.gz'
  45. X4. change to the prg directory : 'cd prg'
  46. X
  47. XYou can start working with prg immediately now.
  48. XThe prg shell skript resides in the prg directory,
  49. Xthe awk and sed skripts required are located in
  50. Xthe lib subdirectory, but the default settings
  51. Xknow about this.
  52. XYou may move the prg shell script into a directory
  53. Xthat is contained in the PATH environment variable
  54. Xany time you want.
  55. X
  56. XFor a personal installation with a different directory
  57. Xstructure take a look at the configuration section
  58. Xof the prg script and adjust the following variables
  59. XPRGDATAPATH    (location of your data)
  60. XPRGLIBPATH    (location of your awk and sed skript)
  61. XTMPDIR        (directory for temporary files)
  62. X
  63. X
  64. END_OF_FILE
  65.   if test 1173 -ne `wc -c <'prg/INSTALL'`; then
  66.     echo shar: \"'prg/INSTALL'\" unpacked with wrong size!
  67.   fi
  68.   # end of 'prg/INSTALL'
  69. fi
  70. if test -f 'prg/README' -a "${1}" != "-c" ; then 
  71.   echo shar: Will not clobber existing file \"'prg/README'\"
  72. else
  73.   echo shar: Extracting \"'prg/README'\" \(2767 characters\)
  74.   sed "s/^X//" >'prg/README' <<'END_OF_FILE'
  75. XWHAT IS PRG ?
  76. X-------------
  77. X
  78. Xprg is a PostScript report generator based on generic input data.  The
  79. Xdata consists of two parts: A description file and a data file.  The
  80. Xfirst file describes the logical structure of the data file.
  81. X
  82. Xprg can be used to manage all kinds of data, like your personal phone
  83. Xbook, addresses, books, music cassettes and so on. Once you've entered
  84. Xyour data you can create reports that contain an arbitrary combination
  85. Xof fields from your data and you may sort them by whatever keys you
  86. Xwant.  You may also retrieve only a subset of the records stored in
  87. Xthe data file; prg contains a parser for simple selection expressions
  88. Xto support this.
  89. X
  90. XPRG runs in a UNIX environment; it only requires standard-tools
  91. X(awk, shell...), there's no need for any compiler.
  92. X
  93. XWHAT'S NEW IN RELEASE 1.1 :
  94. X---------------------------
  95. X
  96. X1. MAJOR NEW FEATURES
  97. X
  98. X1.1. SELECTORS ADDED:
  99. X
  100. X     It is now possible to print a report of a selection of records only.
  101. X     The selection is implemented as an expression that is parsed at
  102. X     runtime to determine whether a record qualifies for a report or not.
  103. X     See the new SELECTION section in the OnLine-Documentation and the
  104. X     manual page for details.
  105. X
  106. X1.2. ONLINE-HELP:
  107. X     You may now query prg for the meaning of any of its parameters using
  108. X     the '-info yourOption' option, i.e.
  109. X     prg -info -select
  110. X     shows you information about the '-select' option.
  111. X
  112. X1.3. SUPPORTING LARGE DATA FILES
  113. X     The PostScript code has been rewritten in order to support arbitrary
  114. X     large data files.
  115. X
  116. X
  117. X2. MINOR NEW FEATURES
  118. X
  119. X2.1. Time-Field allows seconds to be used if field data is preceeded by 's'
  120. X
  121. X2.2. If you want hash characters in your strings replace them by '\hash'
  122. X
  123. X2.3. If a column has the same contents for two succeeding rows i and i+1
  124. X     you may want to use the option '-noDuplicates' to avoid the repetitive
  125. X     printing of this identical contents.
  126. X
  127. X2.4. If the contents of the first column change, a delimiting horizontal
  128. X     line is drawn between these two rows.
  129. X
  130. X2.5. Enhanced handling of time fields (option '-accuracy' added).
  131. X
  132. X2.6. The command line used to produce the program now appears on the
  133. X     title page.
  134. X
  135. X
  136. XWHERE TO GET IT:
  137. X----------------
  138. X
  139. XThe new release 1.1 is currently available from the ftp site
  140. X
  141. Xftp.ubka.uni-karlsruhe.de
  142. X
  143. Xin the directory
  144. X
  145. X/pub/prg
  146. X
  147. XGet the file prg-1.1.tar.gz using binary transfer mode.
  148. X
  149. XIf you have any comments, find bugs etc., drop me a line.
  150. X
  151. X-patsch
  152. X
  153. X--
  154. XPatrick Dockhorn \ Uni-Bibliothek \ Kaiserstrasse 12 \ 76131 Karlsruhe \
  155. X\ e-mail: patsch@ubka.uni-karlsruhe.de,finger=ubkaaix3\ Germany  __o    \
  156. X \  There are two rules for success in life:           \       _`\<,_    \ 
  157. X  \   Rule 1: Don't tell people everything you know.    \     (_)/ (_)    \
  158. X
  159. END_OF_FILE
  160.   if test 2767 -ne `wc -c <'prg/README'`; then
  161.     echo shar: \"'prg/README'\" unpacked with wrong size!
  162.   fi
  163.   # end of 'prg/README'
  164. fi
  165. if test -f 'prg/doc/videos-by-actors-first-name-starts-A-or-B.ps' -a "${1}" != "-c" ; then 
  166.   echo shar: Will not clobber existing file \"'prg/doc/videos-by-actors-first-name-starts-A-or-B.ps'\"
  167. else
  168.   echo shar: Extracting \"'prg/doc/videos-by-actors-first-name-starts-A-or-B.ps'\" \(26882 characters\)
  169.   sed "s/^X//" >'prg/doc/videos-by-actors-first-name-starts-A-or-B.ps' <<'END_OF_FILE'
  170. X%!
  171. X%%Creator: patsch on ubkaaix3 using prg
  172. X%%Title: Videoliste
  173. X%%CreationDate: Fri Jun  3 16:25:12 MST 1994
  174. X%%DocumentFonts: AvantGarde-Book
  175. X%%EndComments
  176. X
  177. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  178. X%                                                            %
  179. X%   prg - patsch's PostScript report generator Release 1.1   %
  180. X%                                                            %
  181. X%         Copyright (C) 1994 Patrick Dockhorn                %
  182. X% Permission to use and modify this software and its         %
  183. X% documentation for any purpose other than its incorporation %
  184. X% into a commercial product is hereby granted without fee.   %
  185. X% Permission to copy and distribute this software and its    %
  186. X% documentation only for non-commercial use is also granted  %
  187. X% without fee, provided, however, that the above copyright   %
  188. X% notice appear in all copies, that both that copyright      %
  189. X% notice and this permission notice appear in supporting     %
  190. X% documentation. The author makes no representations about   %
  191. X% the suitability of this software for any purpose. It is    %
  192. X% provided ``as is'' without express or implied warranty.    %
  193. X%                                                            %
  194. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  195. X
  196. X%%EndProlog
  197. X
  198. X% recode font vector to enable foreign special characters
  199. X% copied from PostScript cookbook
  200. X
  201. X/reencsmalldict 12 dict def
  202. X/ReEncodeSmall
  203. X{
  204. X reencsmalldict begin
  205. X /newcodesandnames exch def
  206. X /newfontname exch def
  207. X /basefontname exch def
  208. X
  209. X /basefontdict basefontname findfont def
  210. X /newfont basefontdict maxlength dict def
  211. X basefontdict
  212. X {
  213. X  exch dup /FID ne
  214. X  {
  215. X   dup /Encoding eq
  216. X   { exch dup length array copy
  217. X     newfont 3 1 roll put }
  218. X   { exch newfont 3 1 roll put }
  219. X   ifelse
  220. X  }
  221. X  { pop pop }
  222. X  ifelse
  223. X } forall
  224. X
  225. X newfont /FontName newfontname put
  226. X newcodesandnames aload pop
  227. X newcodesandnames length 2 idiv
  228. X { newfont /Encoding get 3 1 roll put } repeat
  229. X newfontname newfont definefont pop
  230. X end
  231. X} def
  232. X
  233. X% ------------------------------------------------------------------
  234. X%
  235. X% germanvec is an array that contains positions and character
  236. X% names. The given characters, - they are usually not included
  237. X% in the standard font encoding - are activated at the given
  238. X% positions in the character set.
  239. X% To use your own characters (i.e. /ccedilla, modify
  240. X% the font vector accordingly.
  241. X% The PostScript Language Reference contains the names
  242. X% of characters available as well as a map of unused
  243. X% regions in the standard text encoding.
  244. X% The following octal regions can be used in a standard
  245. X% text encoding without removing other characters:
  246. X% \260, \300, \321-\341, \354-\360, \362-\364, \366-\367, \374-\376
  247. X%
  248. X% ------------------------------------------------------------------
  249. X
  250. X/germanvec [
  251. X 8#300 /adieresis
  252. X 8#311 /Adieresis
  253. X 8#321 /odieresis 
  254. X 8#322 /Odieresis
  255. X 8#323 /udieresis
  256. X 8#324 /Udieresis
  257. X 8#325 /germandbls
  258. X 8#326 /eacute
  259. X 8#327 /egrave
  260. X 8#330 /ecircumflex
  261. X 8#331 /ccedilla
  262. X 8#332 /otilde
  263. X 8#333 /atilde
  264. X 8#334 /ntilde
  265. X 8#335 /copyright
  266. X 8#336 /registered
  267. X 8#337 /trademark
  268. X 8#340 /Ccedilla
  269. X 8#341 /aacute
  270. X] def
  271. X
  272. X% ------------------------------------------------------------------
  273. X%
  274. X% - Umlaute - 
  275. X%
  276. X% Activate the new font encoding that includes foreign umlauts
  277. X% for the font selected by the user by FONTNAME.
  278. X%
  279. X% ------------------------------------------------------------------
  280. X
  281. X/Umlaute
  282. X{
  283. X /AvantGarde-Book /GermanFont germanvec ReEncodeSmall
  284. X} def
  285. X
  286. X% ------------------------------------------------------------------
  287. X%
  288. X% (text) width clipshow -
  289. X%
  290. X% The given text is shown at the current point. Before the text
  291. X% is displayed, a clip rectangle is placed around it with the
  292. X% given width. This avoids overlapping text in adjacent columns.
  293. X%
  294. X% ------------------------------------------------------------------
  295. X
  296. X/clipshow
  297. X{
  298. X  gsave
  299. X    newpath x0 1 add y0 1 add moveto 2 sub dup 0 rlineto 
  300. X    0 lsize 2 sub rlineto neg 0 rlineto closepath clip
  301. X    newpath x0 xboff add y0 descent add yboff add moveto show
  302. X  grestore
  303. X} def
  304. X
  305. X% ------------------------------------------------------------------
  306. X%
  307. X% prg-array optimizeColumns -
  308. X%
  309. X% optimizeColumns uses the given array of application specific data
  310. X% to update its internal state as far as the maximum column width
  311. X% required is concerned.
  312. X%
  313. X% ------------------------------------------------------------------
  314. X
  315. X/optimizeColumns
  316. X{
  317. X  % --------------------------------------------------------------------------
  318. X  % use all the information given to compute optimal column widths & font size
  319. X  % --------------------------------------------------------------------------
  320. X  {
  321. X    /elem exch def               % define current element
  322. X    % (elem is) == elem ==
  323. X    0 1 nColumns 1 sub              % loop through all columns
  324. X    {
  325. X      /i exch def
  326. X      fieldMulti i get (W) eq
  327. X      {
  328. X    % Weightened Selection: Column Width is constant, i.e.
  329. X    % compute only once
  330. X    maxSizes i get 0 eq % not yet computed -> do it
  331. X    {
  332. X      /legend true def
  333. X      /len 0 def
  334. X      multiWeightSelTitles i get
  335. X      {
  336. X        stringwidth pop multiOff dup add add len add /len exch def
  337. X      } forall % for all strings in the multi weight info array
  338. X      % put information about the size of the field into the array
  339. X      maxSizes i len put        
  340. X    } if
  341. X      }     % end if current column is weightened selection
  342. X      {     % if current column is NOT a weightened selection
  343. X    % simply compute the width of the given strings using
  344. X    % their maximum multiplicity as given in /colMultiplicity
  345. X    % the strings are concatenated using the delimiter string
  346. X    /cnt 0 def  % counter for maximum multiplicity
  347. X    /len xboff dup add def
  348. X    /maxMultiplicity colMultiplicity i get def
  349. X    elem i get
  350. X    dup /nMultis exch length def
  351. X    {
  352. X      /len exch stringwidth pop len add
  353. X      % should I append the delimiter ?
  354. X      /cnt cnt 1 add def
  355. X      cnt nMultis ne
  356. X      cnt maxMultiplicity ne and
  357. X      {
  358. X        delimiter stringwidth pop add def
  359. X      }
  360. X      {
  361. X        def exit
  362. X      } ifelse
  363. X    } forall
  364. X    % if size exceeds maximum, store it
  365. X    maxSizes i get len lt
  366. X    {
  367. X      maxSizes i len put
  368. X    } if
  369. X      } ifelse      % end if current column is *not* a weightened selection
  370. X    } for           % for all selected columns
  371. X  } forall  % end optimization loop through the input array
  372. X} def
  373. X
  374. X% ------------------------------------------------------------------
  375. X%
  376. X% - postOptimization -
  377. X%
  378. X% Uses the information obtained from calling optimizeColumns
  379. X% (several times, if the input data is too large)
  380. X% and mixes it with field widths given by the user to compute
  381. X% the new font size and applies the resulting scaling factor
  382. X% to a number of internal parameters.
  383. X%
  384. X% ------------------------------------------------------------------
  385. X
  386. X/postOptimization
  387. X{
  388. X  0 1 nColumns 1 sub
  389. X  {
  390. X    /i exch def
  391. X    colSizes i get -1 eq    % no size given -> use the computed size
  392. X    {
  393. X      colSizes i maxSizes i get put
  394. X      debug 
  395. X      { 
  396. X    (\012 Computed width for column ') print colNames i get print 
  397. X    (' to ) print colSizes i get 12 string cvs print
  398. X      } if
  399. X    }
  400. X    {
  401. X      debug
  402. X      { 
  403. X    (\012 Using specified width \() print colSizes i get
  404. X    12 string cvs print ( points\) for column ') print
  405. X    colNames i get print
  406. X      } if
  407. X    } ifelse
  408. X  } for
  409. X  0 colSizes { add } forall
  410. X  /total exch def
  411. X  /factor hspace total div def                      % scaling factor
  412. X  /fsize fsize factor mul def
  413. X  /GermanFont findfont fsize scalefont setfont
  414. X  % update column size information
  415. X  [ colSizes { factor mul } forall ] /colSizes exch def
  416. X  /multiOff multiOff factor mul def
  417. X
  418. X  /sbbox 4 array def                   %% compute scaled bounding box
  419. X  0 1 3
  420. X  {
  421. X    /i exch def
  422. X    sbbox i bbox i get fsize mul 1000 div put
  423. X  } for
  424. X  
  425. X  % size of one line, taking descent and font size into account
  426. X  /lsize sbbox 3 get sbbox 1 get
  427. X  sub yboff dup add add def    
  428. X  
  429. X  % current descent value, used to position the characters vertically
  430. X  % within a line
  431. X  /descent sbbox 1 get neg def        %% 0 is origin, lly is therefore negative descent
  432. X  
  433. X  debug { (\012 Descent set to ) print descent 10 string cvs print (\012) print } if
  434. X  /nLines vspace lsize div cvi def    %% number of lines on one page according to line size
  435. X  
  436. X  % update available vertical space
  437. X  /vspace nLines lsize mul def
  438. X  
  439. X  % compute expected number of pages
  440. X  totalEntries nLines 1 sub idiv totalEntries nLines 1 sub mod 0 ne { 1 add } if
  441. X  /nPages exch def
  442. X  /nPagesStr nPages 10 string cvs def
  443. X  
  444. X  debug { (\012 Report will consist of ) print nLines 10 string cvs print ( lines per page.) print } if
  445. X  debug { (\012 Optimization finished, using font size ) print fsize 10 string cvs print } if
  446. X
  447. X  % ------------------------------------------------------------------
  448. X  % print title page
  449. X  % ------------------------------------------------------------------
  450. X  
  451. X  showtitle
  452. X  {
  453. X    16 dict begin
  454. X      top
  455. X      newpath
  456. X      gsave
  457. X    0 0 moveto title true charpath pathbbox 
  458. X    /tury exch def
  459. X    /turx exch def
  460. X    /tlly exch def
  461. X    /tllx exch def
  462. X    % the '18 sub' is to leave some space at the border for
  463. X    % additional infos
  464. X    newpath hspace 18 sub turx tllx sub div /sfak exch def
  465. X    hspace 2 div vspace 2 div translate sfak sfak scale
  466. X    tllx turx sub 2 div tlly tury sub 2 div moveto title show
  467. X      grestore
  468. X      % compute positions required for user name and sorting criteria
  469. X      % debug { (\012 size of title string is ) print turx tllx sub 10 string cvs print } if
  470. X      % debug { (\012 scaling factor is ) print sfak 10 string cvs print } if
  471. X      /topoff vspace tury tlly sub sfak mul add 2 div yboff add lsize add def
  472. X      /botoff sortFields length lsize mul def
  473. X      userstr stringwidth pop ( presents) stringwidth pop add neg hspace add 2 div
  474. X      topoff moveto userstr show ( presents) show
  475. X      % display the sort keys
  476. X      (Sorting Criteria:) stringwidth pop neg hspace add 2 div /scx exch def
  477. X      scx botoff moveto (Sorting Criteria:) show
  478. X      sortFields
  479. X      {
  480. X    /botoff botoff lsize sub def
  481. X    scx botoff moveto show
  482. X      } forall
  483. X      % show date and page info
  484. X      0 vspace lsize sub moveto datestr show
  485. X      hspace timestr stringwidth pop sub vspace lsize sub moveto timestr show
  486. X      0 0 moveto totalEntries 16 string cvs show ( lines) show
  487. X      % display total number of pages
  488. X      hspace ( pages) stringwidth pop sub 
  489. X      nPagesStr stringwidth pop sub 0 moveto
  490. X      nPagesStr show ( pages) show
  491. X      gsave
  492. X    /GermanFont findfont 6 scalefont setfont
  493. X    gsave
  494. X      0 vspace 2 div translate 90 rotate
  495. X      commandLine dup stringwidth pop 2 div neg 0
  496. X      moveto show
  497. X    grestore
  498. X    gsave
  499. X      hspace vspace 2 div translate -90 rotate
  500. X      (thanks for using patsch's PostScript Report Generator - (C) 1994 Patrick Dockhorn)
  501. X      dup stringwidth pop 2 div neg 0
  502. X      moveto show
  503. X    grestore
  504. X      grestore
  505. X    end
  506. X    showpage
  507. X  } if
  508. X  
  509. X  % ------------------------------------------------------------------
  510. X  % print legend if any weightened selection present
  511. X  % ------------------------------------------------------------------
  512. X  
  513. X  legend
  514. X  {
  515. X    12 dict begin
  516. X      top
  517. X      /y0 vspace lsize sub def
  518. X      newpath (Additional Information) dup
  519. X      stringwidth pop neg
  520. X      dup /tmpsw exch def
  521. X      hspace add 2 div y0 moveto show
  522. X      tmpsw 0 rlineto stroke
  523. X      /y0 y0 lsize dup add sub def
  524. X      /nhits 0 def
  525. X      0 1 nColumns 1 sub
  526. X      {
  527. X    /i exch def
  528. X    fieldMulti i get (W) eq
  529. X    {
  530. X      /ybuf y0 def
  531. X      /nhits nhits 1 add def
  532. X      nhits 2 mod 0 eq
  533. X      {
  534. X        /x0 hspace 2 div xboff add def
  535. X      }
  536. X      {
  537. X        /x0 xboff def
  538. X      } ifelse
  539. X      newpath x0 y0 moveto (Explanation for column ') show
  540. X      colNames i get show (' :) show
  541. X      x0 y0 lineto stroke newpath
  542. X      /mss 0 def
  543. X      /scarr multiWeightSelTitles i get def
  544. X      /ltarr multiWeightSelFullTitles i get def
  545. X      scarr
  546. X      {
  547. X        stringwidth pop dup mss gt { /mss exch def } { pop } ifelse
  548. X      } forall
  549. X      
  550. X      0 1 scarr length 1 sub
  551. X      {
  552. X        /j exch def
  553. X        /y0 y0 lsize sub def
  554. X        x0 y0 moveto scarr j get show
  555. X        x0 mss add xboff dup add add y0 moveto ltarr j get show
  556. X      } for
  557. X      nhits 2 mod 0 eq
  558. X      {
  559. X        /y0 y0 lsize dup add sub def
  560. X      }
  561. X      {
  562. X        /y0 ybuf def
  563. X      } ifelse
  564. X    } if
  565. X      } for
  566. X      showpage
  567. X    end
  568. X  } if
  569. X} def
  570. X
  571. X
  572. X% ------------------------------------------------------------------
  573. X%
  574. X% prg-array createReport -
  575. X%
  576. X% Prints the data given in prg-array (which is in a format specified
  577. X% through the -format option) nicely formatted. Does all the pagebreak,
  578. X% handling, rotation etc.
  579. X%
  580. X% ------------------------------------------------------------------
  581. X
  582. X/createReport
  583. X{
  584. X  % ------------------------------------------------------------------  
  585. X  % handle all array elements
  586. X  % ------------------------------------------------------------------  
  587. X
  588. X  {
  589. X    /elem exch def          % define current element
  590. X    line 0 eq                   % Top of page ?
  591. X    {
  592. X      top
  593. X      /x0 0 def
  594. X      /y0 vspace def              % start value for y
  595. X      0 setlinewidth              % set line width for bounding box
  596. X      newpath 0 0 moveto hspace 0 rlineto 0 vspace rlineto
  597. X      hspace neg 0 rlineto closepath
  598. X      /y0 y0 lsize sub def
  599. X      0 y0 moveto hspace 0 rlineto stroke
  600. X
  601. X      gsave
  602. X    /GermanFont findfont 6 scalefont setfont
  603. X    newpath 0 vspace yboff add moveto title show delimiter show datestr show
  604. X    newpath hspace (Page ) stringwidth pop sub page 1 add 10 string cvs /pagestr exch def
  605. X    pagestr stringwidth pop sub ( / ) stringwidth pop sub nPagesStr stringwidth pop sub 
  606. X    vspace yboff add moveto (Page ) show pagestr show ( / ) show nPagesStr show
  607. X      grestore
  608. X      
  609. X      0 1 nColumns 1 sub
  610. X      {
  611. X    /i exch def
  612. X    /cs colSizes i get def
  613. X    debug
  614. X    {
  615. X      (\012 Column size for ') print colNames i get print (' is ) print
  616. X      cs 10 string cvs print (\012) print
  617. X    } if
  618. X    
  619. X    fieldMulti i get (W) eq       % multi-field -> special title
  620. X    {
  621. X      /xbuf x0 def
  622. X      /j 0 def
  623. X      /offArr colMultiOffsets i get def
  624. X      % debug { (\012 offArr for column ) print colNames i get print ( is \012) print offArr == } if
  625. X      /mwsl multiWeightSelTitles i get length def
  626. X      multiWeightSelTitles i get
  627. X      {
  628. X        dup stringwidth pop /mssize exch def    % save string size
  629. X        newpath x0 multiOff add y0 yboff add descent add moveto % position
  630. X        show
  631. X        offArr j x0 put    % save current x position
  632. X        j 0 gt j mwsl ne and 
  633. X        {
  634. X          x0 y0 lsize add moveto 0 vspace neg 
  635. X          rlineto stroke 
  636. X        } if
  637. X        /j j 1 add def
  638. X        mssize multiOff dup add add
  639. X        dup x0 add /x0 exch def
  640. X        neg cs add /cs exch def
  641. X      } forall
  642. X      /x0 xbuf def
  643. X      
  644. X%           debug 
  645. X%           { 
  646. X%             (\012 Updated colMultiOffsets[) print i 10 string cvs print
  647. X%               (] to the following offset array:\012) print offArr == 
  648. X%           } if
  649. X
  650. X      colMultiOffsets i offArr put
  651. X    }
  652. X    {
  653. X      colNames i get cs clipshow
  654. X    } ifelse
  655. X    i 0 gt { newpath x0 y0 lsize add moveto 0 vspace neg rlineto stroke } if
  656. X    /x0 x0 colSizes i get add def
  657. X      } for % end for all columns
  658. X      debug { (\012 Multi-Column offset array:\012) print colMultiOffsets == } if
  659. X      
  660. X      /y0 y0 lsize sub def
  661. X    } if % end if first line of page  
  662. X    
  663. X    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  664. X    %
  665. X    % Standard Procedure for a single entry
  666. X    %
  667. X    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  668. X
  669. X    newpath
  670. X    /x0 0 def
  671. X    0 1 nColumns 1 sub
  672. X    {
  673. X      /i exch def
  674. X      fieldMulti i get (W) eq         % Weightened selection
  675. X      {
  676. X    /done false def
  677. X    % debug { (\012 Handling multi field ') print colNames i get print ('\012) print } if
  678. X    elem i get
  679. X    {
  680. X      % debug { (\012 Checking weightened selection ) print dup == } if
  681. X      dup 1 get /val exch def
  682. X      0 get /cat exch def
  683. X      % search for the position of the category
  684. X      /idx 0 def
  685. X      multiWeightSelTitles i get
  686. X      {
  687. X        cat eq % category match -> show the corr. value
  688. X        {
  689. X          colMultiOffsets i get idx get multiOff add
  690. X          cat stringwidth pop add val stringwidth pop sub
  691. X          y0 yboff add descent add moveto val show
  692. X          /done true def
  693. X          exit
  694. X        } if
  695. X        /idx idx 1 add def
  696. X      } forall
  697. X      done { exit } if
  698. X    } forall
  699. X      }       % end if current column is weightened selection
  700. X      {       % if current column is NOT a weightened selection
  701. X    % simply compute the width of the given strings using
  702. X    % their maximum multiplicity as given in /colMultiplicity
  703. X    % the strings are concatenated using the delimiter string
  704. X    
  705. X    % first check if the current element is the same
  706. X    % as the previous one, if so, and duplicate elim.
  707. X    % is selected, nothing is displayed
  708. X    % (except if this is the first line of a new page)
  709. X
  710. X    /displayThis true def
  711. X    noDupls line 0 ne and
  712. X    {
  713. X      /tidx 0 def
  714. X      true
  715. X      elem i get
  716. X      {
  717. X        lastElem i get tidx get eq and
  718. X        /tidx tidx 1 add def
  719. X      } forall
  720. X      not /displayThis exch def
  721. X    } if
  722. X
  723. X    displayThis
  724. X    {
  725. X      line 0 ne i 0 eq and
  726. X      {
  727. X        0 y0 lsize add yboff add moveto hspace 0 rlineto stroke
  728. X      } if
  729. X      /cnt 0 def    % counter for maximum multiplicity
  730. X      /xwidth colSizes i get def
  731. X      /maxMultiplicity colMultiplicity i get def
  732. X      /xbuf x0 def
  733. X      elem i get
  734. X      dup /nMultis exch length def
  735. X      nMultis 1 eq
  736. X      {
  737. X        % only one entry -> check for the field type and
  738. X        % display numeric values right justified
  739. X        
  740. X        
  741. X        0 get
  742. X        fieldTypes i get dup (N) eq exch (T) eq or
  743. X        {
  744. X          dup stringwidth pop neg x0 add xwidth add
  745. X          xboff dup add sub
  746. X          /x0 exch def xwidth clipshow
  747. X        }
  748. X        {
  749. X          % no numeric field
  750. X          xwidth clipshow
  751. X        } ifelse
  752. X      }
  753. X      {
  754. X        % more than one entry
  755. X        {
  756. X          dup
  757. X          xwidth clipshow
  758. X          stringwidth pop dup neg xwidth add /xwidth exch def
  759. X          x0 add /x0 exch def
  760. X          % should I append the delimiter ?
  761. X          /cnt cnt 1 add def
  762. X          cnt nMultis ne
  763. X          cnt maxMultiplicity ne and
  764. X          {
  765. X        delimiter xwidth clipshow
  766. X        delimiter stringwidth pop dup
  767. X        x0 add /x0 exch def neg xwidth add
  768. X        /xwidth exch def
  769. X          }
  770. X          {
  771. X        exit    % leave if maximum multiplicity reached
  772. X          } ifelse
  773. X        } forall
  774. X      } ifelse
  775. X      /x0 xbuf def
  776. X    } if          % if entry should be shown at all
  777. X      } ifelse        % end if not a weightened selection
  778. X      
  779. X      /x0 x0 colSizes i get add def
  780. X      
  781. X    } for             % end for all columns
  782. X    
  783. X    % one line is finished
  784. X    % debug { (\012 Line ) print line 10 string cvs print ( printed.) print } if
  785. X
  786. X    /line line 0 eq
  787. X    { line 2 add } { line 1 add } ifelse 
  788. X    dup nLines ge { pop 0 /page page 1 add def showpage } if def
  789. X    /y0 y0 lsize sub def        % new y starting position
  790. X    /lastElem elem def        % remember last element for duplicate elimination
  791. X  } forall            % end for all data
  792. X} def
  793. X
  794. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  795. X%%
  796. X%%           M     M    A      III   N     N
  797. X%%           MM   MM   A A      I    NN    N
  798. X%%           M M M M  A   A     I    N N   N
  799. X%%           M  M  M A     A    I    N  N  N
  800. X%%           M     M AAAAAAA    I    N   N N
  801. X%%           M     M A     A    I    N    NN
  802. X%%           M     M A     A   III   N     N
  803. X%%
  804. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  805. X
  806. X128 dict begin    % start a large user dictionary
  807. X
  808. XUmlaute         % activate german (or, more generally, foreign Umlauts)
  809. X
  810. X/GermanFont findfont 12 scalefont setfont        % select font
  811. X
  812. X% Dynamic data for output header
  813. X
  814. X/cm { 28.346456 mul } def    %% definition of a cm based in points
  815. X/pageWidth 21.0 cm def    %% Width of a page
  816. X/pageHeight 29.7 cm def    %% Height of a page
  817. X/hoff 1.2 cm def                 %% horizontal skip value
  818. X/voff 1.2 cm def                 %% vertical skip value
  819. X
  820. X/landscape false def    %% Print in landscape mode ?
  821. X/datestr (03.06.94) def    %% today's date
  822. X/timestr (16:25:13) def    %% current time
  823. X/userstr (patsch) def        %% user running the program
  824. X/fsize 12 def        %% base font used
  825. X/title (Videoliste) def        %% title for the report
  826. X/delimiter (, ) def    %% delimiter string for multi-fields
  827. X/noDupls true def         %% display values if same for two succeeding rows ?
  828. X
  829. X% define size variables depending on landscape parameter
  830. X
  831. Xlandscape            
  832. X{
  833. X /lph pageWidth def
  834. X /lpw pageHeight def
  835. X}
  836. X{
  837. X /lpw pageWidth def
  838. X /lph pageHeight def
  839. X} ifelse
  840. X
  841. X% procedure called when new page is started 
  842. X
  843. X/top
  844. X{
  845. X  landscape
  846. X  {
  847. X    -90 rotate pageHeight neg 0 translate
  848. X  } if
  849. X  hoff voff translate
  850. X} def
  851. X
  852. X
  853. X%% ------------------------------------------------------------------
  854. X%% the following arrays were created by the prg.awk program
  855. X%% ------------------------------------------------------------------
  856. X
  857. X% requested size of the selected columns
  858. X/colSizes [ -1 -1 -1 -1 -1 ] def
  859. X
  860. X% Titles of the selected columns 
  861. X/colNames [ (Actor/Actress) (Title) (Nr.) (Index) (Length) ] def
  862. X
  863. X% Maximum multiplicity of the selected columns 
  864. X/colMultiplicity [ 1 1 1 1 1 ] def
  865. X
  866. X% Offsets within fields with multiplicity greater than one
  867. X/colMultiOffsets [ [ 0 ] [ 0 ] [ 0 ] [ 0 ] [ 0 ] ] def
  868. X
  869. X% fieldTypes: describe the type of the fields to be shown
  870. X/fieldTypes [ (A) (A) (N) (N) (T) ] def
  871. X
  872. X% fieldMulti: holds the information whether a field may hold multiple elements
  873. X/fieldMulti [ (M) (O) (O) (O) (O) ] def
  874. X
  875. X% titles for weightened multiple selection fields
  876. X/multiWeightSelTitles [ [] [] [] [] [] ] def
  877. X
  878. X
  879. X% full titles for weightened multiple selection fields
  880. X/multiWeightSelFullTitles [ [] [] [] [] [] ] def
  881. X
  882. X% fields used for sorting
  883. X/sortFields [(Ascending 'Actor/Actress')(Ascending 'Title') ] def
  884. X
  885. X% total entries in this report
  886. X/totalEntries 399 def
  887. X
  888. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  889. X%% define global variables used for optimization
  890. X%% and printing
  891. X%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  892. X
  893. X/optimize true def           %% optimize output size ?
  894. X/debug false def              %% PostScript debugging
  895. X/showtitle true def         %% display title page ?
  896. X/commandLine (command line used: /u/patsch/bin/prg videos -format ACT#TIT#NUM#IDX#LEN -sortby ACT#TIT -noDuplicates -cbsc 0 -select stdin) def        %% how the program was invoked
  897. X/line 0 def                         %% current line
  898. X/page 0 def                         %% current page
  899. X/hspace lpw hoff dup add sub def    %% space available horizontally
  900. X/vspace lph voff dup add sub def    %% space available vertically
  901. X/xboff 3 def                        %% box offset horizontally
  902. X/yboff 2 def                        %% box offset horizontally
  903. X/multiOff 2 def                     %% Offset for multiple weightened selection
  904. X/x0 0 def                           %% start value for x
  905. X  
  906. X/nColumns colSizes length def       %% number of columns
  907. X/bbox /GermanFont findfont 
  908. X/FontBBox get [ exch aload pop ] def %% Bounding-Box (scale-independent)
  909. X/legend false def             %% draw a legend on the second page ?
  910. X/maxSizes nColumns array def        %% array to hold the maximum values
  911. X
  912. X0 1 nColumns 1 sub            %% NULL the maxSizes array
  913. X{
  914. X maxSizes exch 0 put
  915. X} for
  916. X
  917. X%% compute default values for column widths if no optimization requested
  918. X
  919. Xoptimize not
  920. X{
  921. X  % compute default sizes for the columns (if no explicit data given)
  922. X  0 1 nColumns 1 sub 
  923. X  {
  924. X    /i exch def colSizes i colSizes i get
  925. X    dup -1 eq { pop hspace nColumns div } if put
  926. X    fieldMulti i get (W) eq { /legend true def } if
  927. X  } for
  928. X} if % no optimization -> compute default values
  929. X
  930. X% ------------------------------------------------------------------
  931. X% ------------------------------ DATA ------------------------------
  932. X% ------------------------------------------------------------------
  933. X
  934. X[
  935. X[[(Beasley,Allyce)][(Monstrum,Das)][(24)][(2)][(3:00:00)]]
  936. X[[(Bedelia,Bonnie)][(Stirb Langsam II)][(2)][(1)][(1:58:00)]]
  937. X[[(Bedelia,Bonnie)][(Stirb Langsam)][(2)][(0)][(2:05:00)]]
  938. X[[(Blessed,Brian)][(Robin Hood - K\321nig der Diebe)][(8)][(0)][(2:17:00)]]
  939. X[[(Brown,Bryan)][(Der Auftragskiller)][(28)][(1)][()]]
  940. X[[(Brown,Bryan)][(FX 2)][(10)][(0)][(1:43:00)]]
  941. X[[(Call,Brandon)][(Blinde Wut)][(6)][(1)][(1:22:00)]]
  942. X[[(Cobbs,Bill)][(New Jack City)][(22)][(0)][(1:36:00)]]
  943. X[[(Corley,Annie)][(Monstrum,Das)][(24)][(2)][(3:00:00)]]
  944. X[[(Datcher,Alex)][(Passagier 57)][(24)][(1)][(1:20:00)]]
  945. X[[(Dennehy,Brian)][(Einsame Zeit f\323r Helden)][(16)][(0)][(1:41:00)]]
  946. X[[(Dennehy,Brian)][(FX 2)][(10)][(0)][(1:43:00)]]
  947. X[[(Desalvo,Anne)][(Ich bin Du und Du bist nichts)][(13)][(1)][(1:49:00)]]
  948. X[[(DeSando,Anthony)][(New Jack City)][(22)][(0)][(1:36:00)]]
  949. X[[(Djola,Badja)][(The Last Boy Scout)][(18)][(1)][(1:42:00)]]
  950. X[[(Doyle-Murray,Brian)][(Und t\300glich gr\323\325t das Murmeltier)][(26)][(0)][(1:37:00)]]
  951. X[[(Doyon,Bruno)][(Stirb Langsam)][(2)][(0)][(2:05:00)]]
  952. X[[(Duke,Bill)][(Predator)][(17)][(0)][(1:40:00)]]
  953. X[[(Evans,Art)][(Stirb Langsam II)][(2)][(1)][(1:58:00)]]
  954. X[[(Finney,Albert)][(Miller's Crossing)][(10)][(1)][(1:50:00)]]
  955. X[[(Fonda,Bridget)][(Doc Hollywood)][(9)][(1)][(1:37:00)]]
  956. X[[(Garcia,Andy)][(Ein ganz normaler Held)][(21)][(1)][()]]
  957. X[[(Glover,Brian)][(Alien III)][(23)][(1)][(1:51:00)]]
  958. X[[(Godunov,Alexander)][(Stirb Langsam)][(2)][(0)][(2:05:00)]]
  959. X[[(Greenwood,Bruce)][(Passagier 57)][(24)][(1)][(1:20:00)]]
  960. X[[(Halsey,Brett)][(Lion of the Desert)][(9)][(0)][(2:07:00)]]
  961. X[[(Heald,Anthony)][(Das Schweigen der L\300mmer)][(5)][(1)][(1:50:00)]]
  962. X[[(Hopkins,Anthony)][(Das Schweigen der L\300mmer)][(5)][(1)][(1:50:00)]]
  963. X[[(Hughes,Barnard)][(Doc Hollywood)][(9)][(1)][(1:37:00)]]
  964. X[[(James,Brion)][(Blade Runner)][(22)][(1)][(1:50:00)]]
  965. X[[(Janner,Brigitte)][(Manta - Der Film)][(8)][(1)][(1:29:00)]]
  966. X[[(Katarina,Anna)][(Jugger,Die)][(13)][(0)][(1:39:00)]]
  967. X[[(MacDowell,Andie)][(Und t\300glich gr\323\325t das Murmeltier)][(26)][(0)][(1:37:00)]]
  968. X[[(Matthews,Al)][(Aliens II)][(4)][(1)][(24:00)]]
  969. X[[(McGill,Bruce)][(The Last Boy Scout)][(18)][(1)][(1:42:00)]]
  970. X[[(McKinney,Bill)][(T\321dliches Abenteuer)][(16)][(1)][(1:37:00)]]
  971. X[[(Motta,Bess)][(Terminator)][(3)][(0)][(1:43:00)]]
  972. X[[(Murray,Bill)][(Und t\300glich gr\323\325t das Murmeltier)][(26)][(0)][(1:37:00)]]
  973. X[[(Nunn,Bill)][(New Jack City)][(22)][(0)][(1:36:00)]]
  974. X[[(Paton,Angela)][(Und t\300glich gr\323\325t das Murmeltier)][(26)][(0)][(1:37:00)]]
  975. X[[(Paxton,Bill)][(Aliens II)][(4)][(1)][(24:00)]]
  976. X[[(Paxton,Bill)][(Einsame Zeit f\323r Helden)][(16)][(0)][(1:41:00)]]
  977. X[[(Payne,Allen)][(New Jack City)][(22)][(0)][(1:36:00)]]
  978. X[[(Payne,Bruce)][(Passagier 57)][(24)][(1)][(1:20:00)]]
  979. X[[(Reynolds,Burt)][(T\321dliches Abenteuer)][(16)][(1)][(1:37:00)]]
  980. X[[(Rickman,Alan)][(Robin Hood - K\321nig der Diebe)][(8)][(0)][(2:17:00)]]
  981. X[[(Rickman,Alan)][(Stirb Langsam)][(2)][(0)][(2:05:00)]]
  982. X[[(Schwarzenegger,Arnold)][(Predator)][(17)][(0)][(1:40:00)]]
  983. X[[(Schwarzenegger,Arnold)][(Terminator II - Judgement Day)][(3)][(1)][(2:08:00)]]
  984. X[[(Schwarzenegger,Arnold)][(Terminator)][(3)][(0)][(1:43:00)]]
  985. X[[(Smith,Brooke)][(Das Schweigen der L\300mmer)][(5)][(1)][(1:50:00)]]
  986. X[[(Wallage,Basil)][(Wedlock)][(6)][(0)][(1:36:00)]]
  987. X[[(Willis,Bruce)][(Stirb Langsam II)][(2)][(1)][(1:58:00)]]
  988. X[[(Willis,Bruce)][(Stirb Langsam)][(2)][(0)][(2:05:00)]]
  989. X[[(Willis,Bruce)][(The Last Boy Scout)][(18)][(1)][(1:42:00)]]
  990. X[[(Wisniewski,Andreas)][(Stirb Langsam)][(2)][(0)][(2:05:00)]]
  991. X] dup optimizeColumns postOptimization createReport
  992. Xline 0 eq not { showpage } if
  993. Xend    % end large user dictionary
  994. X%%TRAILER
  995. X
  996. END_OF_FILE
  997.   if test 26882 -ne `wc -c <'prg/doc/videos-by-actors-first-name-starts-A-or-B.ps'`; then
  998.     echo shar: \"'prg/doc/videos-by-actors-first-name-starts-A-or-B.ps'\" unpacked with wrong size!
  999.   fi
  1000.   # end of 'prg/doc/videos-by-actors-first-name-starts-A-or-B.ps'
  1001. fi
  1002. if test -f 'prg/lib/prg.awk' -a "${1}" != "-c" ; then 
  1003.   echo shar: Will not clobber existing file \"'prg/lib/prg.awk'\"
  1004. else
  1005.   echo shar: Extracting \"'prg/lib/prg.awk'\" \(31418 characters\)
  1006.   sed "s/^X//" >'prg/lib/prg.awk' <<'END_OF_FILE'
  1007. XBEGIN {
  1008. X  passOne = 1;
  1009. X  scanDES = 0;
  1010. X  exprError = 0;
  1011. X  selectAll=0;
  1012. X  if (length(select) == 0)
  1013. X   selectAll=1;
  1014. X  nSortFields = split(sortby,sortFields);
  1015. X  selectionIndex=1;
  1016. X}
  1017. X
  1018. X$1 == "END_DESCRIPTION" {
  1019. X  scanDES = 0; 
  1020. X  newEntry = 1;
  1021. X  nEntries = 0;
  1022. X  # index variable for selection,
  1023. X  # equal to nEntries during buildup
  1024. X  cec = 0;
  1025. X  lastNum = -1;
  1026. X  desLines = NR;
  1027. X}
  1028. X
  1029. XscanDES == 1 {
  1030. X  name=$1;
  1031. X  # define name for the fields
  1032. X  fieldName[name] = $2;  
  1033. X  # define field type         
  1034. X  fieldType[name] = $3;
  1035. X  # define field multiplicity 
  1036. X  fieldMulti[name] = $4; 
  1037. X  if ( ( $4 == "W" ) || ( $4 == "S" ) )
  1038. X    { 
  1039. X      fieldNSelections[name] = NF - 4; 
  1040. X      for (i = 5 ; i <= NF ; i++) 
  1041. X    fieldSelection[name,i-5] = $i; 
  1042. X    }
  1043. X} 
  1044. X
  1045. X$1 == "BEGIN_DESCRIPTION" {
  1046. X  scanDES = 1;
  1047. X}
  1048. X
  1049. X(scanDES == 0) && (NF == 0) {
  1050. X  if (lastEmpty == 0)     
  1051. X    {
  1052. X      # special for videos: compute offset !
  1053. X      videos[nEntries,"OFF",1] = timeCount;
  1054. X      timeCount+=videos[nEntries,"LEN",1]; 
  1055. X      # check whether the entry is selected at all
  1056. X      if (selectAll)
  1057. X    {
  1058. X      nEntries++;
  1059. X      cec = nEntries;
  1060. X    }
  1061. X      else
  1062. X    {
  1063. X      if (isSelected())
  1064. X        {
  1065. X          if (debugExpr)
  1066. X        printf("\n-------> ENTRY SELECTED (MATCH)!\n");
  1067. X          nEntries++;
  1068. X          cec = nEntries;
  1069. X        }
  1070. X      else
  1071. X        {
  1072. X              # restore current entry
  1073. X          for (name in fieldName )
  1074. X        videos[nEntries,name,0] = 0;
  1075. X        }
  1076. X    }
  1077. X      if ((nEntries % 100) == 0) printf(".");
  1078. X    }
  1079. X  lastEmpty=1;
  1080. X}
  1081. X
  1082. X(scanDES == 0) && (NF > 0) && ($1 != "END_DESCRIPTION") {
  1083. X  lastEmpty=0;
  1084. X  if (($1 == "NUM") && ($2 != lastNum)) 
  1085. X    {
  1086. X      lastNum = $2; 
  1087. X      timeCount=0; 
  1088. X    }
  1089. X
  1090. X  if (fieldName[$1] == "")
  1091. X    printf("\nWarning in line %d : No description for the field <%s> exists !\n",NR-desLines,$1);
  1092. X
  1093. X  offset = videos[nEntries,$1,0];
  1094. X  videos[nEntries,$1,0] = offset+NF-1; 
  1095. X  for (i = 2 ; i <= NF ; i++)
  1096. X   videos[nEntries,$1,i-1+offset] = $i;
  1097. X  videos[nEntries,$1,NF+offset] = NR-desLines;
  1098. X  if ((videos[nEntries,$1,0] > 1) && 
  1099. X      (!((fieldMulti[$1] == "M") || (fieldMulti[$1] == "W"))))
  1100. X    {
  1101. X      printf("\nFehler in Zeile %d: Feld hat kein Multi-Attribut (weder 'M' noch 'W' sondern '%s'.",NR,fieldMulti[$1]);
  1102. X      printf("\nKontext: Field <%s>, line <%s>.",$1,$0);
  1103. X    }
  1104. X}
  1105. X
  1106. XEND {
  1107. X  if (exprError) exit -77;
  1108. X  passOne = 0;
  1109. X  if (debugExpr)
  1110. X    printf("\n------------------------------------------------------------------\n PASS ONE COMPLETE\n------------------------------------------------------------------");
  1111. X  if (debug) 
  1112. X    {
  1113. X      for ( name in fieldName )
  1114. X    { 
  1115. X      printf("\nFeld %s [ Typ %s] : %s",name,fieldType[name],fieldName[name]);
  1116. X      if ( ( fieldMulti[name] == "W" ) || 
  1117. X           ( fieldMulti[name] == "S" ) ) 
  1118. X        for (i = 0 ; i < fieldNSelections[name] ; i++)
  1119. X          printf("\n                  : Selektion No.%2d : %s",i+1,fieldSelection[name,i]); }
  1120. X      printf("\n------------------------------------------------------------------");
  1121. X      for (n = 0 ; n < nEntries; n++) 
  1122. X    { 
  1123. X      for (name in fieldName)          
  1124. X        { 
  1125. X          nMultis = videos[n,name,0]; 
  1126. X          printf("\n%s: ",name);
  1127. X          for (i = 1 ; i <= nMultis ; i++) 
  1128. X        {
  1129. X          if (i > 1) printf(",");
  1130. X          printf("%s",videos[n,name,i]); 
  1131. X        }
  1132. X        }
  1133. X    }
  1134. X    }
  1135. X
  1136. X  ##################################################################
  1137. X  #
  1138. X  # create the postscript header information 
  1139. X  #
  1140. X  ##################################################################
  1141. X
  1142. X  nFields = split(format,formatStrings);
  1143. X  
  1144. X  printf("%% requested size of the selected columns\n/colSizes [") > tmpHeader;
  1145. X  for ( i = 1 ; i <= nFields ; i++ )
  1146. X    printf(" %g",extractColumnWidth(formatStrings[i])) > tmpHeader;
  1147. X  
  1148. X  printf(" ] def\n\n%% Titles of the selected columns \n/colNames [") > tmpHeader;
  1149. X  for ( i = 1 ; i <= nFields ; i++ )
  1150. X    printf(" (%s)",fieldName[extractColumnName(formatStrings[i])]) > tmpHeader; 
  1151. X  
  1152. X  printf(" ] def\n\n%% Maximum multiplicity of the selected columns \n/colMultiplicity [") > tmpHeader;
  1153. X  for ( i = 1 ; i <= nFields ; i++ )
  1154. X    printf(" %s",extractColumnMultiplicity(formatStrings[i])) > tmpHeader; 
  1155. X  
  1156. X  printf(" ] def\n\n%% Offsets within fields with multiplicity greater than one\n/colMultiOffsets [") > tmpHeader;
  1157. X  for ( i = 1 ; i <= nFields ; i++ )
  1158. X    {
  1159. X      printf(" [") > tmpHeader;
  1160. X      nm = extractColumnMultiplicity(formatStrings[i]);
  1161. X      for (j = 0 ; j < nm ; j++)
  1162. X    printf(" 0") > tmpHeader;
  1163. X      printf(" ]") > tmpHeader;
  1164. X    }
  1165. X  
  1166. X  printf(" ] def\n") > tmpHeader;
  1167. X  
  1168. X  # Feld-Typ Info
  1169. X  printf("\n%% fieldTypes: describe the type of the fields to be shown\n/fieldTypes [") > tmpHeader;
  1170. X  for ( i = 1 ; i <= nFields ; i++ )
  1171. X    printf(" (%s)",fieldType[extractColumnName(formatStrings[i])]) > tmpHeader; 
  1172. X  
  1173. X  printf(" ] def\n") > tmpHeader;
  1174. X  
  1175. X  # Feld-Multi Info
  1176. X  printf("\n%% fieldMulti: holds the information whether a field may hold multiple elements\n/fieldMulti [") > tmpHeader;
  1177. X  for ( i = 1 ; i <= nFields ; i++ )
  1178. X    printf(" (%s)",fieldMulti[extractColumnName(formatStrings[i])]) > tmpHeader; 
  1179. X  
  1180. X  printf(" ] def\n") > tmpHeader;
  1181. X
  1182. X  #
  1183. X  # create the titles for weightened selections 
  1184. X  #
  1185. X
  1186. X  printf("\n%% titles for weightened multiple selection fields\n/multiWeightSelTitles [") > tmpHeader;
  1187. X  for ( i = 1 ; i <= nFields ; i++ )
  1188. X    {
  1189. X      name = extractColumnName(formatStrings[i]);
  1190. X      if ( fieldMulti[name] == "W" )
  1191. X    {
  1192. X      printf(" [") > tmpHeader;
  1193. X      for (k = 0 ; k < fieldNSelections[name] ; k++) 
  1194. X        { 
  1195. X          selstr=fieldSelection[name,k];
  1196. X          printf("(") > tmpHeader;
  1197. X          do 
  1198. X        {
  1199. X          j = index(selstr,"_");
  1200. X          if (j > 0)
  1201. X            {
  1202. X              printf("%s",substr(selstr,j+1,1)) > tmpHeader;
  1203. X              selstr=substr(selstr,j+2);
  1204. X            }
  1205. X        } while (j > 0); 
  1206. X          printf(")") > tmpHeader;
  1207. X        }
  1208. X      printf("]") > tmpHeader;
  1209. X    }
  1210. X      else printf(" []") > tmpHeader; 
  1211. X    } 
  1212. X  printf(" ] def\n") > tmpHeader;
  1213. X
  1214. X  # compute the full titles
  1215. X  printf("\n\n%% full titles for weightened multiple selection fields\n/multiWeightSelFullTitles [") > tmpHeader;
  1216. X  for ( i = 1 ; i <= nFields ; i++ )
  1217. X    {
  1218. X      name = extractColumnName(formatStrings[i]);
  1219. X      if ( fieldMulti[name] == "W" )
  1220. X    {
  1221. X      printf(" [ ") > tmpHeader;
  1222. X      for (j = 0 ; j < fieldNSelections[name] ; j++) 
  1223. X        {
  1224. X          selstr=fieldSelection[name,j];
  1225. X          gsub("_","",selstr);
  1226. X          printf(" (%s)",selstr) > tmpHeader; 
  1227. X        }
  1228. X      printf(" ]") > tmpHeader;
  1229. X    }
  1230. X      else
  1231. X    printf(" []") > tmpHeader;
  1232. X    } 
  1233. X  printf(" ] def\n") > tmpHeader;
  1234. X
  1235. X  #
  1236. X  # parse the data stored in the videos array and create the appropriate
  1237. X  # output that is then sorted using standard unix procedures
  1238. X  #
  1239. X  # create sorting information first
  1240. X
  1241. X
  1242. X  # return number of sort fields
  1243. X  printf("%d\n",nSortFields+1) > sprintf("%s.nsf",tmpHeader);
  1244. X
  1245. X  # check if sort fields are valid at all
  1246. X  printf("#!/bin/sh\nsort -t '#' ") > sortFileName;
  1247. X
  1248. X  printf("\n%% fields used for sorting\n/sortFields [") > tmpHeader;
  1249. X  for (i = 1 ; i <= nSortFields ; i++)
  1250. X    {
  1251. X      reverse=doReverseSort(sortFields[i]);
  1252. X      name = extractSortFieldName(sortFields[i]);
  1253. X      
  1254. X      if (reverse)
  1255. X    printf("(Descending") > tmpHeader;
  1256. X      else
  1257. X    printf("(Ascending") > tmpHeader;
  1258. X      printf(" '%s')",fieldName[name]) > tmpHeader;
  1259. X
  1260. X      if ((fieldType[name] == "A") ||
  1261. X      (fieldType[name] == "N") ||
  1262. X      (fieldType[name] == "T"))
  1263. X    {
  1264. X      if (fieldMulti[name] == "W")
  1265. X        { 
  1266. X          printf("\nIt's not possible to sort using a weightened multiple selection");
  1267. X          printf("\nfield as you tried with the field <%s>.\n",name);
  1268. X          exit -1;
  1269. X        }
  1270. X      else
  1271. X        {
  1272. X          printf(" +%db",i-1) > sortFileName;
  1273. X          if (reverse)
  1274. X        printf("r") > sortFileName;
  1275. X          if ((fieldType[name] == "N") || (fieldType[name] == "T"))
  1276. X        printf("n") > sortFileName;
  1277. X          if (casecomp == 0)
  1278. X        printf("f") > sortFileName;
  1279. X        }
  1280. X    }
  1281. X      else
  1282. X    {
  1283. X      printf("\nYou selected the field <%s> for sorting, but it has got the illegal type <%s>.\n",
  1284. X         name,fieldType[name]); 
  1285. X      exit -2;
  1286. X    }
  1287. X    }
  1288. X  printf(" ] def\n") > tmpHeader;
  1289. X  
  1290. X  printf(" -o ${1}.srt $1") > sortFileName;
  1291. X
  1292. X  # loop through all the tapes I got
  1293. X
  1294. X  totalEntries = 0;
  1295. X  
  1296. X  if (nEntries == 0)
  1297. X    {
  1298. X      printf("\nNo entries selected !\n");
  1299. X      printf(" ") > tmpData;
  1300. X      exit -3;
  1301. X    }
  1302. X  for (n = 0 ; n < nEntries; n++)
  1303. X    {
  1304. X      for (i = 1 ; i <= nSortFields ; i++) sortCounter[i] = 1;
  1305. X      # loop over multiple selection fields used as sort keys
  1306. X      entryDone = 0;
  1307. X      do
  1308. X    {
  1309. X      totalEntries++;
  1310. X      if ((totalEntries % 100) == 0) printf(".");
  1311. X          # buffer for the sort keys
  1312. X      lbuf=""
  1313. X      
  1314. X      ###########################################
  1315. X      # handle the prefixed sort keys
  1316. X      ###########################################
  1317. X
  1318. X      for (i = 1 ; i <= nSortFields ; i++)
  1319. X        {
  1320. X          name = extractSortFieldName(sortFields[i]);
  1321. X          sstr=videos[n,name,sortCounter[i]];
  1322. X          z = index(sstr,"$");
  1323. X          if (z > 0)
  1324. X        lbuf=lbuf sprintf("%s,%s#",substr(sstr,z+1),substr(sstr,1,z-1));
  1325. X          else 
  1326. X        {
  1327. X          if (length(sstr) == 0)
  1328. X            {
  1329. X                     # if string is empty prefix it with some special
  1330. X             # characters to have it appear at the end of the report
  1331. X              if (doReverseSort(sortFields[i]))
  1332. X            lbuf = lbuf sprintf("!!!!!#");
  1333. X              else
  1334. X            lbuf = lbuf sprintf("}}}}}#");
  1335. X            }
  1336. X          else
  1337. X            {
  1338. X              if (fieldType[name] == "T")
  1339. X            lbuf = lbuf sprintf("%d#",getTimeNumeric(sstr));
  1340. X              else
  1341. X            lbuf = lbuf sprintf("%s#",sstr);
  1342. X            }
  1343. X        }
  1344. X        }
  1345. X      
  1346. X      printMe=1;
  1347. X      lbuf = lbuf "[";
  1348. X      for ( i = 1 ; (i <= nFields) && (printMe) ; i++ )
  1349. X        {
  1350. X          name = extractColumnName(formatStrings[i]);
  1351. X              #
  1352. X          #
  1353. X          # create postscript string depending on input data type
  1354. X          #
  1355. X          #
  1356. X          # check whether the current column is a key; if so, force the
  1357. X          # currently selected key to appear in the column !
  1358. X          special=0;
  1359. X          if (!(selectAll))
  1360. X              {
  1361. X            # check whether the current entry is selected at all !
  1362. X            for (j = 1 ; (j <= nSortFields) && (printMe) ; j++)
  1363. X            {
  1364. X            sname = extractSortFieldName(sortFields[j]);
  1365. X            if ((sname == name) && (fieldMulti[name] == "M"))
  1366. X              {
  1367. X                cec = n;
  1368. X                selectionIndex = sortCounter[j];
  1369. X                        printMe = isSelected();
  1370. X              }
  1371. X          }
  1372. X          }
  1373. X          if (printMe)
  1374. X        {
  1375. X          for (j = 1 ; j <= nSortFields; j++)
  1376. X            {
  1377. X              sname = extractSortFieldName(sortFields[j]);
  1378. X              if (sname == name)
  1379. X            {
  1380. X              special=1;
  1381. X              sstr=videos[n,sname,sortCounter[j]];
  1382. X              # time data type ?
  1383. X              if ((fieldType[sname] == "T") && (length(sstr) > 0))
  1384. X                lbuf = lbuf getTime(videos[n,sname,1]);
  1385. X              else
  1386. X                {
  1387. X                  z = index(sstr,"$");
  1388. X                  if (z > 0)
  1389. X                lbuf = lbuf sprintf("[(%s,%s)]",substr(sstr,z+1),substr(sstr,1,z-1));
  1390. X                  else
  1391. X                lbuf = lbuf sprintf("[(%s)]",sstr);
  1392. X                }
  1393. X            }
  1394. X            }
  1395. X          
  1396. X          if (special == 0)
  1397. X            {
  1398. X              # time data type
  1399. X              if (fieldType[name] == "T")
  1400. X            lbuf=lbuf getTime(videos[n,name,1]);
  1401. X              else
  1402. X            {
  1403. X              # ASCII or NUMERIC
  1404. X                  lbuf = lbuf "[";
  1405. X              if (fieldMulti[name] == "M") # multiple values possible
  1406. X                {
  1407. X                  nMultis = videos[n,name,0]; 
  1408. X                  for (j = 1 ; j <= nMultis ; j++) 
  1409. X                {
  1410. X                  namstr=videos[n,name,j];
  1411. X                  gsub("\\$"," ",namstr);
  1412. X                  lbuf = lbuf sprintf("(%s)",namstr);
  1413. X                }
  1414. X                }
  1415. X              else
  1416. X                {
  1417. X                  # weightened selection
  1418. X                  if (fieldMulti[name] == "W") 
  1419. X                {
  1420. X                  nMultis = videos[n,name,0]; 
  1421. X                  for (j = 1 ; j <= nMultis ; j++) 
  1422. X                    {
  1423. X                      selstr=videos[n,name,j];
  1424. X                      gsub("\\$"," ",selstr);
  1425. X                      len = length(selstr);
  1426. X                      val=substr(selstr,len,1);
  1427. X                      if ((val < "0") || (val > "9"))
  1428. X                    {
  1429. X                      printf("\nFehler in Zeile %d der Eingabedatei:",videos[n,name,nMultis+1]);
  1430. X                      printf("\nEin Feld der Kategorie 'Weightened Selection'");
  1431. X                      printf("\nwurde nicht mit der erforderlichen Wertung (0-9) beendet.\n");
  1432. X                      exit -4;
  1433. X                    }
  1434. X                      lbuf = lbuf sprintf("[(%s)(%s)]",substr(selstr,1,len-1),val);
  1435. X                    }
  1436. X                }
  1437. X                  else
  1438. X                {
  1439. X                  selstr=videos[n,name,1];
  1440. X                  if ((fieldMulti[name] == "S") && (selstr != ""))
  1441. X                    {
  1442. X                      selOk = 0;
  1443. X                      # consistency check
  1444. X                      for (j = 0 ; j < fieldNSelections[name] ; j++)
  1445. X                    if (fieldSelection[name,j] == selstr) selOk = 1;
  1446. X                      if (selOk == 0)
  1447. X                    {
  1448. X                      printf("\nFehler in Zeile %d der Eingabedatei:",videos[n,name,nMultis+1]);
  1449. X                      printf("\nEinem Feld der Kategorie 'Selection' wurde ein nicht definierter");
  1450. X                      printf("\nWert (%s) zugewiesen. Erlaubt sind die folgenden Werte:\n",selstr);
  1451. X                      for (j = 0 ; j < fieldNSelections[name] ; j++)
  1452. X                        {
  1453. X                          if (j > 0) printf(", ");
  1454. X                          printf("%s",fieldSelection[name,j]);
  1455. X                        }
  1456. X                      exit -5;
  1457. X                    }
  1458. X                    }
  1459. X                  # just the standard one-entry field category
  1460. X                  gsub("\\$"," ",selstr);
  1461. X                  lbuf = lbuf sprintf("(%s)",selstr);
  1462. X                }
  1463. X                }
  1464. X                  # end if no multiple field
  1465. X              lbuf = lbuf "]";
  1466. X            } 
  1467. X            # end if field type is *not* time
  1468. X            }
  1469. X            # end if no special case (key appears in format string)
  1470. X        } 
  1471. X        # end if entry should be printed at all
  1472. X        }
  1473. X        # end for all fields selected in the format string
  1474. X      
  1475. X      # print the current line into the output file
  1476. X      if (printMe)
  1477. X        printf("%s]\n",lbuf) >> tmpData;
  1478. X      
  1479. X      # increase counter until all multiple fields are done
  1480. X      entryDone=0;
  1481. X      i = nSortFields;
  1482. X      do
  1483. X        {
  1484. X          carry=0;
  1485. X          sname = extractSortFieldName(sortFields[i]);
  1486. X          sortCounter[i]=sortCounter[i]+1;
  1487. X          if (sortCounter[i] > videos[n,sname,0])
  1488. X        {
  1489. X          carry=1;
  1490. X          sortCounter[i] = 1;
  1491. X          i--;
  1492. X          if (i <= 0)
  1493. X            entryDone = 1;
  1494. X        }
  1495. X        } while ((carry == 1) && (entryDone == 0));
  1496. X    } while (entryDone == 0);
  1497. X    }
  1498. X  printf("\n%% total entries in this report\n/totalEntries %d def\n",totalEntries) >> tmpHeader;
  1499. X  # end for all entries in the database
  1500. X}
  1501. X
  1502. X##################################################################
  1503. X##################################################################
  1504. X# FUNCTION DEFINITIONS
  1505. X##################################################################
  1506. X##################################################################
  1507. X
  1508. X##################################################################
  1509. X#
  1510. X# Extract functions for format specifiers
  1511. X# Generic format is:
  1512. X# COLUMN_NAME:WIDTH-NUMBER
  1513. X#
  1514. X# where
  1515. X# COLUMN_NAME is the name of the column to display
  1516. X# WIDTH is the width to be used to display the column (in cm)
  1517. X# NUMBER is the maximal number of hits to be displayed if
  1518. X#        the field has a multiplicity higher than one.
  1519. X#
  1520. X# WIDTH defaults to a very simple value computed by dividing
  1521. X# the total page width by the number of columns, NUMBER defaults to 1.
  1522. X#
  1523. X##################################################################
  1524. X
  1525. Xfunction extractColumnName(str)
  1526. X{
  1527. X  # look for colon which indicates space information to use
  1528. X  z1 = index(str,":");
  1529. X  z2 = index(str,"-");
  1530. X  # no info specified
  1531. X  if ( (z1 == 0) && (z2 == 0) ) return str;
  1532. X  else
  1533. X    {
  1534. X      if (z1 == 0)
  1535. X    return substr(str,1,z2-1);
  1536. X      else
  1537. X    {
  1538. X      if (z2 == 0)
  1539. X        return substr(str,1,z1-1);
  1540. X      else
  1541. X        {
  1542. X          if (z2 < z1) { tmp = z1; z1 = z2; z2 = tmp; }
  1543. X          return substr(str,z1,z2-z1);
  1544. X        }
  1545. X    }
  1546. X    }
  1547. X}
  1548. X
  1549. X####################################################################
  1550. X# extracts the width of a column specified in a format string
  1551. X####################################################################
  1552. X
  1553. Xfunction extractColumnWidth(str)
  1554. X{
  1555. X  # look for colon which indicates space information to use
  1556. X  z1 = index(str,":");
  1557. X  z2 = index(str,"-");
  1558. X  # no info specified
  1559. X  if (z1 == 0) return -1;
  1560. X  else
  1561. X    {
  1562. X      val = -1;
  1563. X      if (z2 == 0)
  1564. X    val = substr(str,z1+1);    
  1565. X      else
  1566. X    {
  1567. X      if (z2 > z1)
  1568. X        val = substr(str,z1+1,z2-z1-1);
  1569. X      else
  1570. X        val = substr(str,z1+1);
  1571. X    }
  1572. X      return val*unit;
  1573. X    }
  1574. X}
  1575. X
  1576. X#######################################################################
  1577. X# extracts the multiplicity of a column specified in the format string
  1578. X#######################################################################
  1579. X
  1580. Xfunction extractColumnMultiplicity(str)
  1581. X{
  1582. X  # look for colon which indicates space information to use
  1583. X  name = extractColumnName(str);
  1584. X
  1585. X  # Weightened Selection always displays all its members
  1586. X  if (fieldMulti[name] == "W")
  1587. X    return fieldNSelections[name];
  1588. X  z1 = index(str,":");
  1589. X  z2 = index(str,"-");
  1590. X  if (z2 == 0) return "1";    # no info specified
  1591. X  else
  1592. X    {
  1593. X      if (z1 == 0)
  1594. X    return substr(str,z2+1);    # no width info given
  1595. X      else
  1596. X    {
  1597. X      if (z1 > z2)            # width info follows
  1598. X        return substr(str,z2+1,z1-z2-1);
  1599. X      else
  1600. X        return substr(str,z2+1);    # multi info at end
  1601. X    }
  1602. X    }
  1603. X}
  1604. X
  1605. X##################################################################
  1606. X# extract the field name from a sort field, i.e.
  1607. X# removes a leading dash, if there is one
  1608. X##################################################################
  1609. X
  1610. Xfunction extractSortFieldName(str)
  1611. X{
  1612. X z = index(str,"-");
  1613. X if (z == 0) return str;
  1614. X else
  1615. X   {
  1616. X     if (z == 1)
  1617. X       return substr(str,2);
  1618. X     else
  1619. X       {
  1620. X     printf("\n in a sort field specification.");
  1621. X     printf("\nA dash indicating the reverse ordering of");
  1622. X     printf("\na field may *ONLY* appear in front of the sort field's name.");
  1623. X     printf("\nThe sort field <%s> does not match this requirement.\n",str);
  1624. X     exit -6;
  1625. X       }
  1626. X   }
  1627. X}
  1628. X##################################################################
  1629. X# extract the information whether a sort field should be ordered
  1630. X# in reverse order.
  1631. X##################################################################
  1632. X
  1633. Xfunction doReverseSort(str)
  1634. X{
  1635. X  return  index(str,"-");
  1636. X}
  1637. X
  1638. X##################################################################
  1639. X# getTime: gets time formatted
  1640. X##################################################################
  1641. X
  1642. Xfunction getTime(data)
  1643. X{
  1644. X  if (index(data,"s") == 1)
  1645. X    seconds = substr(data,2);
  1646. X  else
  1647. X    seconds = data*60;
  1648. X  
  1649. X  if (seconds == 0)
  1650. X    return "[()]";
  1651. X  else
  1652. X    {
  1653. X      if (accuracy == "minutes")
  1654. X    seconds=int(seconds/60);
  1655. X      if (accuracy == "hours")
  1656. X    seconds=int(seconds/3600);
  1657. X
  1658. X      hours=int(seconds/3600);
  1659. X      hseconds=seconds%3600;
  1660. X      minutes=int(hseconds/60);
  1661. X      seconds=seconds%60;
  1662. X
  1663. X      if (hours == 0)
  1664. X    {
  1665. X      if (minutes == 0)
  1666. X        return(sprintf("[(%2d)]",seconds));
  1667. X      else
  1668. X        return(sprintf("[(%d:%02d)]",minutes,seconds));
  1669. X    }
  1670. X      else
  1671. X    return(sprintf("[(%d:%02d:%02d)]",hours,minutes,seconds));
  1672. X    }
  1673. X}
  1674. X
  1675. X#####################################################################
  1676. X# getTimeNumeric: prints a time record as a numeric value (seconds)
  1677. X#####################################################################
  1678. X
  1679. Xfunction getTimeNumeric(data)
  1680. X{
  1681. X  if (index(data,"s") == 1)
  1682. X    return(substr(data,2));
  1683. X  else
  1684. X    return 60*data;
  1685. X}
  1686. X
  1687. X##################################################################
  1688. X# isSelected: Checks whether the current record is selected
  1689. X#             as far as the given selector is concerned.
  1690. X##################################################################
  1691. X
  1692. Xfunction isSelected()
  1693. X{
  1694. X  if (debugExpr)
  1695. X    {
  1696. X      printf("\n\n------------------------------------------------------------------");
  1697. X      printf("\nDebugging expression '%s' for entry %d.",select,cec);
  1698. X      printf("\n------------------------------------------------------------------\n");
  1699. X    }
  1700. X
  1701. X return evalExpr(select);
  1702. X}
  1703. X
  1704. X
  1705. X##################################################################
  1706. X# evalExpr: evaluates the given expression with respect to
  1707. X#           the current record (indicated by cec).
  1708. X##################################################################
  1709. X
  1710. Xfunction evalExpr(expr,ex1,ex2,operator,name,flag,i)
  1711. X{
  1712. X if (debugExpr)
  1713. X  printf("\nevalExpr<%s>",expr);
  1714. X if (index(expr,"!") == 1)
  1715. X   {
  1716. X     if (debugExpr)
  1717. X       printf("\n<%s> : returning !evalExpr(%s).",expr,substr(expr,2));
  1718. X     return !(evalExpr(substr(expr,2)));
  1719. X   }
  1720. X
  1721. X
  1722. X if (!(bracesOk(expr)))
  1723. X   {
  1724. X     showSelector();printf("The expression <%s> has a problem with its round brackets.\n",expr);
  1725. X     exprError=1; exit -7;
  1726. X   }
  1727. X
  1728. X if (index(expr,"(") == 0)
  1729. X   {
  1730. X     if (debugExpr)
  1731. X       printf("\nevalExpression: Expression is simple <%s>.",expr);
  1732. X     return expr;
  1733. X   }
  1734. X
  1735. X # get operators and operands
  1736. X
  1737. X ex1=evalExpr(getOperand1(expr));
  1738. X operator = getOperator(expr);
  1739. X ex2 = evalExpr(getOperand2(expr));
  1740. X
  1741. X if (operator == "contains")
  1742. X   {
  1743. X     # special handling of 'contains' operator of the
  1744. X     # field used is a sort key !
  1745. X     # this should not be done, better use == directly.
  1746. X
  1747. X     if (substr(ex1,1,3) == "_M_")
  1748. X       ret = fieldContains(substr(ex1,4),ex2);
  1749. X     else
  1750. X       {
  1751. X     showSelector();
  1752. X     exprError = 1;
  1753. X     printf("The 'contains' operator must not be applied if the field does not have");
  1754. X     printf("\nthe 'M' attribute for the ability to hold multiple entries.");
  1755. X     printf("\nThis error also occurs if you specified the correct field, i.e. one");
  1756. X     printf("\nwith the 'M' attribute, but also specified it as a sort key.");
  1757. X     printf("\nIn this case use the == operator instead.\n");
  1758. X     exit -21;
  1759. X       }
  1760. X   }
  1761. X else
  1762. X   {
  1763. X     # another special handling: if a field with attribute 'M'
  1764. X     # was compared using *not* the contains operator.
  1765. X     # this is only possible if the field appears in the sort key fields !
  1766. X
  1767. X     flag = 0;     
  1768. X     if (substr(ex1,1,3) == "_M_")
  1769. X       {
  1770. X     name=substr(ex1,4);
  1771. X
  1772. X     if (isSortKey(name))
  1773. X       {
  1774. X             # if the user attempts to select a single entry
  1775. X             # from a field with 'M' attribute, the evaluation
  1776. X             # of the selection expression has to be postponed
  1777. X             # until the single entries are evaluated during
  1778. X             # the data buildup phase, i.e. AFTER the whole
  1779. X             # file with raw data has been read.
  1780. X
  1781. X         if (debugExpr)
  1782. X           printf("\n\n*** EVALUATION OF '%s' %s '%s' POSTPONED, SET TO 1 FOR NOW.",
  1783. X              ex1,operator,ex2,ret);
  1784. X         return 1;
  1785. X       }
  1786. X     else
  1787. X       {
  1788. X         if (debugExpr)
  1789. X           {
  1790. X         printf("\n%s not in SortFields =",name);
  1791. X         for (sf in sortFields) printf("\n%s",sf);
  1792. X           }
  1793. X         flag=1;
  1794. X       }
  1795. X       }
  1796. X
  1797. X     if (flag)
  1798. X       {
  1799. X     showSelector();printf("The operator '%s' may not be used with the field <%s>",operator,substr(ex1,4));
  1800. X     printf("\n       which may hold multiple entries. Use the 'contains' operator instead !\n");
  1801. X     exprError=1; exit -9;
  1802. X       }
  1803. X   }
  1804. X if (operator == "==")
  1805. X   ret = (strequal(ex1,ex2));
  1806. X if (operator == "!=")
  1807. X   ret = (!(strequal(ex1,ex2)));
  1808. X      
  1809. X if (operator == ">=")
  1810. X   ret = (ex1 >= ex2);
  1811. X if (operator == "<=")
  1812. X   ret = (ex1 <= ex2);
  1813. X if (operator == ">")
  1814. X   ret = (ex1 > ex2);
  1815. X if (operator == "<")
  1816. X   ret = (ex1 < ex2);
  1817. X if (operator == "&&")
  1818. X   ret = (ex1 && ex2);
  1819. X if (operator == "||")
  1820. X ret = (ex1 || ex2);
  1821. X
  1822. X if (debugExpr)
  1823. X   printf("\n\n*** RESULT: '%s' %s '%s' -> %d.",
  1824. X      ex1,operator,ex2,ret);
  1825. X return ret;
  1826. X}
  1827. X
  1828. X##################################################################
  1829. X# bracesOk: check whether the braces are alright within an expression
  1830. X##################################################################
  1831. X
  1832. Xfunction bracesOk(str,ob,cb,dummy)
  1833. X{
  1834. X ob = split(str,dummy,"(");
  1835. X cb = split(str,dummy,")");
  1836. X if (ob != cb)
  1837. X   {
  1838. X     if (debugExpr)
  1839. X       showSelector();printf("There are %d opening and %d closing round brackets in <%s>.",
  1840. X          ob,cb,str);
  1841. X     return 0;
  1842. X   }
  1843. X else
  1844. X   return 1;
  1845. X}
  1846. X
  1847. X##################################################################
  1848. X# getOperand1 : gets the first operand from a compound expression
  1849. X# this involves isolating the field identifier and getting the
  1850. X# current value for it.
  1851. X##################################################################
  1852. X
  1853. Xfunction getOperand1(str,xstr,eop,name)
  1854. X{
  1855. X # forget about first bracket
  1856. X xstr = substr(str,2);    
  1857. X if (index(xstr,"("))
  1858. X   {
  1859. X     if (debugExpr)
  1860. X       printf("\nOperand1 of expression <%s> is the expression <%s>.",
  1861. X          str,getExpression(xstr));
  1862. X     return getExpression(xstr);
  1863. X   }
  1864. X # operand is simple
  1865. X eop = index(xstr," ");
  1866. X if (eop == 0)
  1867. X   {
  1868. X     showSelector();printf("Could not identify the end of operand 1 in <%s>.\n",str);
  1869. X     exprError=1; exit -10;
  1870. X   }
  1871. X name=substr(xstr,1,eop-1);
  1872. X
  1873. X # if a field has the multi attribute, a special value is returned IFF
  1874. X # the call is made during the buildup phase and the field is a sort key !
  1875. X # in the second pass the current name is used instead.
  1876. X if ((fieldMulti[name] == "M") && ((passOne) || (!(isSortKey(name)))))
  1877. X   {
  1878. X     if (debugExpr)
  1879. X       printf("\nMulti-Field <%s> selected. Returning special value _M_%s",name,name);
  1880. X     return sprintf("_M_%s",name);
  1881. X   }
  1882. X else
  1883. X   {
  1884. X     if (debugExpr)
  1885. X       printf("\nOperand1 is field <%s> which currently holds <%s>.",name,videos[cec,name,selectionIndex]);
  1886. X     return videos[cec,name,selectionIndex];
  1887. X   }
  1888. X}
  1889. X
  1890. X##################################################################
  1891. X# getExpression: returns an expression enclosed in brackets.
  1892. X##################################################################
  1893. X
  1894. Xfunction getExpression(str,nstr,z,nB,i,c)
  1895. X{
  1896. X  z = index(str,"(");
  1897. X  if (z == 0)
  1898. X    {
  1899. X      if (debugExpr)
  1900. X    printf("\ngetExpression: <%s> does not contain any brackets.",str);
  1901. X      return str;
  1902. X    }
  1903. X  nstr = substr(str,z);
  1904. X  len = length(nstr);
  1905. X  nB = 1;
  1906. X  for (i = 2 ; ( i < len ) && ( nB > 0 ) ; i++)
  1907. X    {
  1908. X      c = substr(nstr,i,1);
  1909. X      if (c == "(") nB++;
  1910. X      if (c == ")") nB--;
  1911. X    }
  1912. X  if (nB == 0)
  1913. X    {
  1914. X      if (debugExpr)
  1915. X    printf("\ngetExpression: got <%s> from <%s>.",substr(nstr,1,i-1),str);
  1916. X      return substr(nstr,1,i-1);
  1917. X    }
  1918. X  else
  1919. X    {
  1920. X      showSelector();printf("Could not get expression with balanced brackets from <%s>.",nxstr);
  1921. X      exprError=1; exit -11;
  1922. X    }
  1923. X}
  1924. X
  1925. X##################################################################
  1926. X# getOperator: returns the name of the operator within the
  1927. X#              current expression
  1928. X##################################################################
  1929. X
  1930. Xfunction getOperator(zstr,str,z1,z2)
  1931. X{
  1932. X  str = skipExpr(zstr);
  1933. X  z1 = index(str," ");
  1934. X  if (z1 == 0)
  1935. X    {
  1936. X      showSelector();printf("Could not find prefixed space in <%s>;\ncould not identify operator.",str);
  1937. X      exprError=1; exit -12;
  1938. X    }
  1939. X  
  1940. X  while ((substr(str,z1,1) == " ") && (z1 < length(str))) z1++;
  1941. X
  1942. X  z2 = index(substr(str,z1)," ")+z1;
  1943. X
  1944. X  if (z2 == 0)
  1945. X    {
  1946. X      showSelector();printf("Could not find postfixed space in <%s>;\ncould not identify operator.",str);
  1947. X      exprError=1; exit -13;
  1948. X    }
  1949. X
  1950. X  if (debugExpr)
  1951. X    printf("\ngetOperator: got <%s> from <%s> (z1 = %d, z2 = %d)",substr(str,z1,z2-z1-1),str,z1,z2);
  1952. X  return substr(str,z1,z2-z1-1);
  1953. X}
  1954. X
  1955. X##################################################################
  1956. X# skipExpr - skip any expression in the given string, i.e.
  1957. X# skipExpr(  ((ACT == Mich*) && (TIT == Das*))  ) returns " && (TIT == Das*))"
  1958. X##################################################################
  1959. X
  1960. Xfunction skipExpr(str,nB,len,c,i)
  1961. X{
  1962. X if (substr(str,2,1) == "(")
  1963. X   {
  1964. X     if (debugExpr)
  1965. X       printf("\nSkipping first operand in expression <%s>",str);
  1966. X     nB=1;
  1967. X     len=length(str);
  1968. X     for (i = 3 ; (i <= len) && (nB != 0) ; i++)
  1969. X       {
  1970. X     c = substr(str,i,1);
  1971. X     if (c == "(") nB++;
  1972. X     if (c == ")") nB--
  1973. X       }
  1974. X     if (nB == 0)
  1975. X       {
  1976. X     if (debugExpr)
  1977. X       printf("\nOperand skipped, returning <%s>",substr(str,i));
  1978. X     return (substr(str,i));
  1979. X       }
  1980. X     else
  1981. X       {
  1982. X     showSelector();
  1983. X     printf("Could not skip first operand in expression <%s>,\nbraces do not match.",substr(str,2));
  1984. X     exprError=1;
  1985. X     exit -20;
  1986. X       }
  1987. X   }
  1988. X else
  1989. X   {
  1990. X     if (debugExpr)
  1991. X       printf("\nskipExpr<%s> - no complex operand found, nothing done.",str);
  1992. X     return str;
  1993. X   }
  1994. X}
  1995. X##################################################################
  1996. X# getOperand2: returns the second operand from an expression
  1997. X##################################################################
  1998. X
  1999. Xfunction getOperand2(zstr,str,z1,z2,val,z,x)
  2000. X{
  2001. X  str = skipExpr(zstr);
  2002. X  z1 = index(str," ");
  2003. X  if (z1 == 0)
  2004. X    {
  2005. X      showSelector();
  2006. X      printf("Could not find prefixed space before operator in <%s>;",str);
  2007. X      printf("\ncould not identify second operand.");
  2008. X      exprError=1; exit -14;
  2009. X    }
  2010. X  
  2011. X  while (substr(str,z1,1) == " ") z1++;
  2012. X  z2 = index(substr(str,z1)," ") + z1;
  2013. X
  2014. X  if (z2 == 0)
  2015. X    {
  2016. X      showSelector();printf("Could not find postfixed space after operator in <%s>;",str);
  2017. X      printf("\ncould not identify second operand.");
  2018. X      exprError=1; exit -15;
  2019. X    }
  2020. X
  2021. X  while (substr(str,z2,1) == " ") z2++;
  2022. X
  2023. X  val = substr(str,z2);
  2024. X  if (debugExpr)
  2025. X    printf("\ngetOperand2: found start of operand = <%s>",val);
  2026. X
  2027. X  if (index(val,"("))
  2028. X    {
  2029. X      if (debugExpr)
  2030. X    printf("\nOperand2 of expression <%s> is the expression <%s>.",
  2031. X          str,getExpression(val));
  2032. X     return getExpression(val);
  2033. X   }
  2034. X
  2035. X  if (index(val,"\042") == 1)
  2036. X    {
  2037. X      z = index(substr(val,2),"\042");
  2038. X      if (z == 0)
  2039. X    {
  2040. X      showSelector();printf("Could not find closing double quote for value <%s>.\n",val);
  2041. X      exprError=1; exit -16;
  2042. X    }
  2043. X      if (debugExpr)
  2044. X    printf("\ngetOperand2: returning <%s>.",substr(val,2,z-2));
  2045. X      return substr(val,2,z-2);
  2046. X    }
  2047. X
  2048. X  # search end of value (i.e. space or bracket)
  2049. X  z1 = index(val," ");
  2050. X  z2 = index(val,")");
  2051. X  if ((z1 == 0) && (z2 == 0))
  2052. X    {
  2053. X      if (debugExpr)
  2054. X    printf("\ngetOperand2: returning whole val = <%s>.",val);
  2055. X      return val;
  2056. X    }
  2057. X
  2058. X  if (z1 == 0)
  2059. X    x = z2;
  2060. X  else
  2061. X    {
  2062. X      if (z2 == 0)
  2063. X    x = z1;
  2064. X      else
  2065. X    {
  2066. X      if (z1 < z2)
  2067. X        x = z1;
  2068. X      else
  2069. X        x = z2;
  2070. X    }
  2071. X    }
  2072. X
  2073. X  if (debugExpr)
  2074. X    printf("\ngetOperand2: returning <%s>.",substr(val,1,x-1));
  2075. X  return substr(val,1,x-1);
  2076. X}
  2077. X
  2078. X##################################################################
  2079. X# fieldContains: Check if the given field contains an entry
  2080. X#                with the given value.
  2081. X##################################################################
  2082. X
  2083. Xfunction fieldContains(name,value,i)
  2084. X{
  2085. X  for (i = 1 ; i <= videos[cec,name,0] ; i++)
  2086. X    {
  2087. X      containerValue=videos[cec,name,i];
  2088. X      if (debugExpr)
  2089. X    printf("\nfieldContains: Comparing field[%d]=<%s> with value=<%s>.",
  2090. X           i,containerValue,value);
  2091. X      if (strequal(containerValue,value))
  2092. X    return 1;
  2093. X    }
  2094. X  if (debugExpr)
  2095. X    printf("\nfieldContains: Sorry, no match in the %d entries stored for field <%s>.",
  2096. X       videos[cec,name,0],name);
  2097. X  return 0;
  2098. X}
  2099. X
  2100. X##################################################################
  2101. X# strequal - check two strings for equality taking the '*' effect
  2102. X# into acount
  2103. X##################################################################
  2104. X
  2105. Xfunction strequal(str1,str2,l2,sci)
  2106. X{
  2107. X  # string comparison is based on sorting criteria,
  2108. X  # i.e. (ACT == H*) finds Anthony$Hopkins, not Harold$Ramis !
  2109. X  if (compareLastNames)
  2110. X    {
  2111. X      sci = index(str1,"$");
  2112. X      if (sci > 0)
  2113. X    str1 = substr(str1,sci+1);
  2114. X    }
  2115. X  l2 = length(str2);
  2116. X  # check for joker
  2117. X  if (substr(str2,l2,1) == "*")
  2118. X    {
  2119. X      if (length(str1) > (l2-1))
  2120. X    return (substr(str1,1,l2-1) == substr(str2,1,l2-1));
  2121. X      else
  2122. X    return 0;
  2123. X    }
  2124. X  else
  2125. X    return str1 == str2;
  2126. X}
  2127. X
  2128. X##################################################################
  2129. X# showSelector - display the current selector string
  2130. X#                as a context to the following error message.
  2131. X##################################################################
  2132. X
  2133. Xfunction showSelector()
  2134. X{
  2135. X printf("\n\nAn error occured while parsing the selector expression");
  2136. X printf("\nyou gave, i.e. <%s>\n",select);
  2137. X}
  2138. X
  2139. X##################################################################
  2140. X# isSortKey - returns 1 if the given string is a sort key
  2141. X##################################################################
  2142. X
  2143. Xfunction isSortKey(name,i)
  2144. X{
  2145. X  smatch=0;
  2146. X  for (i = 1 ; (i <= nSortFields) ; i++)
  2147. X    if (name == extractSortFieldName(sortFields[i]))
  2148. X      return 1;
  2149. X  return 0;
  2150. X}
  2151. END_OF_FILE
  2152.   if test 31418 -ne `wc -c <'prg/lib/prg.awk'`; then
  2153.     echo shar: \"'prg/lib/prg.awk'\" unpacked with wrong size!
  2154.   fi
  2155.   # end of 'prg/lib/prg.awk'
  2156. fi
  2157. if test -f 'prg/lib/prg.sed.UU' -a "${1}" != "-c" ; then 
  2158.   echo shar: Will not clobber existing file \"'prg/lib/prg.sed.UU'\"
  2159. else
  2160.   echo shar: Extracting \"'prg/lib/prg.sed.UU'\" \(476 characters\)
  2161.   sed "s/^X//" >'prg/lib/prg.sed.UU' <<'END_OF_FILE'
  2162. Xbegin 664 prg/lib/prg.sed
  2163. XM<R\@*2\I+V<*<R]<7&AA<V@O(R]G"G,OY"]<7#,P,"]G"G,O]B]<7#,R,2]G
  2164. XM"G,O_"]<7#,R,R]G"G,OQ"]<7#,Q,2]G"G,OUB]<7#,R,B]G"G,OW"]<7#,R
  2165. XM-"]G"G,OWR]<7#,R-2]G"G,O7%Q<(F$O7%PS,# O9PIS+UQ<7")O+UQ<,S(Q
  2166. XM+V<*<R]<7%PB=2]<7#,R,R]G"G,O7%Q<(D$O7%PS,3$O9PIS+UQ<7")/+UQ<
  2167. XM,S(R+V<*<R]<7%PB52]<7#,R-"]G"G,O7%Q<<W-[?2]<7#,R-2]G"G,O7")A
  2168. XM+UQ<,S P+V<*<R]<(F\O7%PS,C$O9PIS+UPB=2]<7#,R,R]G"G,O7")!+UQ<
  2169. XM,S$Q+V<*<R]<(D\O7%PS,C(O9PIS+UPB52]<7#,R-"]G"G,O7'-S>WTO7%PS
  2170. X%,C4O9PH*
  2171. Xend
  2172. END_OF_FILE
  2173.   if test 476 -ne `wc -c <'prg/lib/prg.sed.UU'`; then
  2174.     echo shar: \"'prg/lib/prg.sed.UU'\" unpacked with wrong size!
  2175.   else
  2176.     echo shar: Uudecoding \"'prg/lib/prg.sed'\" \(320 characters\)
  2177.     cat prg/lib/prg.sed.UU | uudecode
  2178.     if test 320 -ne `wc -c <'prg/lib/prg.sed'`; then
  2179.       echo shar: \"'prg/lib/prg.sed'\" uudecoded with wrong size!
  2180.     else
  2181.       rm prg/lib/prg.sed.UU
  2182.     fi
  2183.   fi
  2184.   # end of 'prg/lib/prg.sed.UU'
  2185. fi
  2186. echo shar: End of archive 5 \(of 6\).
  2187. cp /dev/null ark5isdone
  2188. MISSING=""
  2189. for I in 1 2 3 4 5 6 ; do
  2190.     if test ! -f ark${I}isdone ; then
  2191.     MISSING="${MISSING} ${I}"
  2192.     fi
  2193. done
  2194. if test "${MISSING}" = "" ; then
  2195.     echo You have unpacked all 6 archives.
  2196.     rm -f ark[1-9]isdone
  2197. else
  2198.     echo You still must unpack the following archives:
  2199.     echo "        " ${MISSING}
  2200. fi
  2201. exit 0
  2202. exit 0 # Just in case...
  2203.