Search:

Return to previous page

Contents of file 'dvlabel/dvlabel.w':



    1   % File:        dvlabel.w [CWEB source code]
    2   % Created:     December 5, 2003
    3   % Last change: August 10, 2005
    4   % Author:      Fredrik Jonsson
    5   % Description: CWEB source code for the DVLABEL program, which generates
    6   %              TeX source code for typesetting of labels for digital video
    7   %              tapes (DV format, typically used for hand-held video camera
    8   %              recorders). The program is primarily designed to run in
    9   %              interactive mode, but via command-line parameters it also
   10   %              supports batch-mode operation.
   11   %                 A feature of the program is also that it is able to compile
   12   %              the generated TeX source code into PostScript, using the DVIPS
   13   %              program. (The DVIPS program is copyrighted by Radical Eye
   14   %              Software, but is typically included in most TeX distributions
   15   %              under UNIX, Linux, and Microsoft Windows; see the site
   16   %              http://www.radicaleye.com for further information).
   17   %                 For information on the CWEB programming language, see
   18   %              http://www.literateprogramming.com.
   19   % Compilation: Compile this program by using the enclosed Makefile, or use
   20   %              the blocks of the Makefile as listed in section five of the
   21   %              documentation (file dvlabel.ps or dvlabel.pdf). The C source
   22   %              code (as generated from this CWEB code) conforms to the ANSI
   23   %              standard for the C programming language (which is equivalent
   24   %              to the ISO C89 standard for C).
   25   %
   26   % Copyright (C) 2003-2004, Fredrik Jonsson
   27   %
   28   \input epsf
   29   \def\version{1.6}
   30   \def\lastrevdate{August 10, 2005}
   31   \font\eightcmr=cmr8
   32   \font\tensc=cmcsc10
   33   \font\eightcmssq=cmssq8
   34   \font\eightcmssqi=cmssqi8
   35   \font\twentycmcsc=cmcsc10 at 20 truept
   36   \def\dvlabel{{\eightcmr DVLABEL\spacefactor1000}}
   37   \def\poincare{{\eightcmr POINCARE\spacefactor1000}}
   38   \def\magbragg{{\eightcmr MAGBRAGG\spacefactor1000}}
   39   \def\CEE{{\eightcmr C\spacefactor1000}}     % The C programming language
   40   \def\CWEB{{\eightcmr CWEB\spacefactor1000}} % The CWEB programming language
   41   \def\DVIPS{{\eightcmr DVIPS\spacefactor1000}} % The DVIPS program
   42   %
   43   % Define a handy macro for the list of program revisions.
   44   %
   45   \newdimen\citemindent \citemindent=80pt
   46   \newdimen\citemleftskip \citemleftskip=90pt
   47   \def\citem[#1]{\smallbreak\noindent\hbox to 10pt{}%
   48     \hbox to\citemindent{\bf #1\hfill}%
   49     \hangindent\citemleftskip\ignorespaces}
   50   
   51   \datethis
   52   
   53   @*Introduction.
   54   \vskip 120pt
   55   \centerline{\twentycmcsc Dvlabel}
   56   \vskip 20pt
   57   \centerline{Creates TeX source code for typesetting labels for digital
   58     video tapes}
   59   \vskip 2pt
   60   \centerline{(Version \version\ of \lastrevdate)}
   61   \vskip 10pt
   62   \centerline{Written by Fredrik Jonsson}
   63   \vskip 80pt
   64   \noindent
   65   This \CWEB\footnote{${}^\dagger$}{For information on the \CWEB\ programming
   66   language by Donald E.~Knuth, as well as samples of \CWEB\ programs, see
   67   {\tt http://www-cs-faculty.stanford.edu/\~\ \kern -5pt knuth/cweb.html}.
   68   For general information on literate programming, see
   69   {\tt http://www.literateprogramming.com}.}
   70   program generates \TeX\ source code for typesetting of labels for digital
   71   video tapes (DV format, typically used for hand-held video camera recorders).
   72   
   73   Most people have not heard of the \TeX\ system for typesetting mathematical
   74   text, and if they have, they will most probably not use the system for
   75   creating things like labels for video tapes.
   76   However, the output generated by \TeX\ is in many cases absolutely superior
   77   in balance and visual clarity, and in order to benefit from the compactness
   78   and beauty of text processed by \TeX\ even for such basic things as labels
   79   for video tapes, this program generates the necessary \TeX\ code and even
   80   compiles it into printable PostScript.
   81   
   82   The program is primarily designed to run in interactive mode, but via
   83   command-line parameters it also supports batch-mode operation.
   84   A feature of the program is also that it is able to compile
   85   the generated TeX source code into PostScript, using the
   86   \DVIPS\ program.\footnote{$\ddagger$}{The \DVIPS\ program is copyrighted
   87   by Radical Eye Software, but is typically included in most \TeX\ distributions
   88   under UNIX, Linux, and Microsoft Windows; see the site
   89   {\tt http://www.radicaleye.com} for further information.}
   90   \bigskip
   91   \noindent Copyright \copyright\ Fredrik Jonsson, 2003--2005.
   92   All rights reserved.
   93   \vfill
   94   
   95   @*Revision history of the program.
   96   \medskip
   97   
   98   \citem[2003-12-28]{[v.1.0]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
   99   First properly working version of the \dvlabel\ program.
  100   I got the idea of creating this program from the {\tt audio-tape.ps} PostScript
  101   code by Jamie Zawinski. This code is a splendid example of how one can
  102   write a simple PostScript program with the help of a regular ASCII editor,
  103   and by sending the PostScript program to the printer, one gets a neat
  104   printout to be used for tape cassette labels, DAT, or video tapes.
  105   However, whenever one has a new cassette to be labeled, one has to edit
  106   the PostScript source, and for a rookie on PostScript programming this
  107   task is somewhat inconvenient.
  108   Therefore, I decided to create something similar, but with a standalone program
  109   that could be operated either in interactive mode, with the program asking
  110   for the specific information to be entered in the label, or in batch mode.
  111   However, instead of directly generating PostScript, I decided to go for a
  112   language that I know somewhat more in detail, namely plain \TeX, which also
  113   has the benefit of being a language which the author, Donald E.~Knuth, has
  114   decided to keep fixed in order to ensure future compatibility.
  115   
  116   \citem[2003-12-29]{[v.1.1]} {\tt <jonsson@@uni-wuppertal.de>}\hfill\break
  117   Revised the leading blocks (definitions) of the generator of the \TeX-code,
  118   in order to have a more clearly structure of the labels. Included the
  119   {\tt {\char'134}boxit} example from the \TeX-book to have the face, flap, and spine
  120   of the labels neatly structured.
  121   Also finished the parsing engine for the address and table of contents
  122   fields.
  123   
  124   \citem[2004-11-26]{[v.1.2]} {\tt <fredrik.jonsson@@nmrc.ie>}\hfill\break
  125   Added support for supplying \DVIPS\ options via the command line when
  126   invoking \dvlabel. In order to parse for an arbitrary number of \DVIPS\ options
  127   at the command line, it is important to enclose the list of \DVIPS\ options
  128   by quotes, hence forcing the \dvlabel\ program to parse the set of options as
  129   one single string of characters. (The quotes are only necessary if the number
  130   of \DVIPS\ options are two or more.)
  131   Hence, for example, to force \DVIPS\ to generate output pages of US letter
  132   format and at a resolution of 720 dpi one could invoke \dvlabel\ with
  133   {\tt dvlabel --dvipsopts "-tletter -D720" ...}
  134   Also slightly changed the way the input filename is used; now one can specify
  135   only the basic filename, to which the \dvlabel\ program now automatically
  136   appends the suffix {\tt .dvl}, if necessary.
  137   Finally restructured the blocks related to scanning and saving code for
  138   individual DV labels, in order to have the structure ready for making
  139   the program generally capable of scanning one single file containing
  140   an arbitrary number of labels, as for instance if one would keep all
  141   records in one single text file.
  142   
  143   \citem[2004-11-27]{[v.1.3]} {\tt <fredrik.jonsson@@nmrc.ie>}\hfill\break
  144   The \dvlabel\ program now parses multiple label records from the same input
  145   file. Also added the useful feature of crop marks in the generated \TeX\ output
  146   of the program. In its current state, the program only generates labels in one
  147   single horizontal column; this is something that I in the future versions will
  148   change into a $[3\times3]$ array of labels, as soon as I get the {\tt\\vbox}
  149   and {\tt\\hbox} statements of the {\tt\\boxit} definition right.
  150   
  151   \citem[2004-12-28]{[v.1.4]} {\tt <fredrik.jonsson@@nmrc.ie>}\hfill\break
  152   Added the {\tt --headline} and {\tt --linethick} options. Fixed a bug in
  153   the page output, which previously caused \TeX\ to complain about vertical
  154   underfill of the generated pages.
  155   
  156   \citem[2005-01-01]{[v.1.5]} {\tt <fredrik.jonsson@@nmrc.ie>}\hfill\break
  157   Added the {\tt --cropmark} and {\tt --edgeseparation} options. Also fixed a bug
  158   in the vertical label dimensions. Added the |log()| way of displaying log and
  159   error messages.
  160   
  161   \citem[2005-08-10]{[v.1.6]} {\tt <fj@@phys.soton.ac.uk>}\hfill\break
  162   Back in Southampton with my family after a hot summer. Wrote the code for
  163   the |strip_away_path()| routine originally for the \poincare\ program and
  164   immediately decided to adopt the code also into the \dvlabel\ and \magbragg\
  165   programs in order to finally solve the problem with long path strings that
  166   appear in the program name string whenever poincare is called with an explicit
  167   path specified at the command line. The call to the |strip_away_path()| routine
  168   is located in the beginning of the block for command line parsing.
  169   
  170   @*Compiling the source code. The program is written in \CWEB, generating
  171   ANSI-C conforming source code and documentation as \TeX-source, and is to
  172   be compiled using the enclosed Makefile, leaving an executable
  173   file {\tt dvlabel}\footnote{$\dagger$}{On platforms running Windows NT,
  174   Windows 2000, or any other operating system by Microsoft, the executable
  175   file will instead automatically be called {\tt dvlabel.exe}.} and a
  176   PostScript file {\tt dvlabel.ps} (the document you currently are reading),
  177   which contains the full documentation of the program:
  178   \bigskip
  179   {\obeyspaces\obeylines\tt
  180   ~   \#
  181   ~   \# Makefile designed for use with ctangle, cweave, gcc, and plain TeX.
  182   ~   \#
  183   ~   \# Copyright (C) 2003, Fredrik Jonsson <jonsson@@uni-wuppertal.de>
  184   ~   \#
  185   ~   CTANGLE  = ctangle
  186   ~   CC       = gcc
  187   ~   CCOPTS   = -O2 -Wall -ansi -pedantic \# follow ISO C89 (ANSI) strictly
  188   ~   LNOPTS   = -lm
  189   ~   CWEAVE   = cweave
  190   ~   TEX      = tex
  191   ~   DVIPS    = dvips
  192   ~   DVIPSOPT = -ta4 -D1200
  193   ~   ~
  194   ~   all: dvlabel.exe dvlabel.ps
  195   ~   ~
  196   ~   dvlabel.exe: dvlabel.o \# generate the executable file
  197   ~           \$(CC) \$(CCOPTS) -o dvlabel dvlabel.o \$(LNOPTS)
  198   ~   ~
  199   ~   dvlabel.o: dvlabel.c \# generate the object file
  200   ~           \$(CC) \$(CCOPTS) -c dvlabel.c
  201   ~   ~
  202   ~   dvlabel.c: dvlabel.w \# generate C code from the CWEB source
  203   ~           \$(CTANGLE) dvlabel
  204   ~   ~
  205   ~   dvlabel.ps: dvlabel.dvi \# generate the PostScript documentation
  206   ~           \$(DVIPS) \$(DVIPSOPT) dvlabel.dvi -o dvlabel.ps
  207   ~   ~
  208   ~   dvlabel.dvi: dvlabel.tex \# generate the device-independent documentation
  209   ~           \$(TEX) dvlabel.tex
  210   ~   ~
  211   ~   dvlabel.tex: dvlabel.w \# generate plain TeX code from the CWEB source
  212   ~           \$(CWEAVE) dvlabel
  213   ~   ~
  214   ~   clean:
  215   ~   ~       -rm -Rf *.c *.o *.exe
  216   ~   ~       -rm -Rf *.tex *.aux *.log *.toc *.idx *.scn *.dvi}
  217   \bigskip
  218   
  219   @*Running the program. The program is entirely controlled by the command
  220   line options supplied when invoking the program.
  221   To start the program in interactive mode, simply run {\tt dvlabel} from
  222   the command line, without any command line options.
  223   \medskip
  224   \noindent{\bf Example I:} In the following excerpt
  225   from an interactive terminal session, where a leading asterisk ({\tt *})
  226   in a line indicates the user-supplied input to the program, a DV label is
  227   generated as Encapsulated PostScript, stored in a file named {\tt fig.eps}.
  228   \bigskip
  229   {\obeyspaces\obeylines\tt
  230   ~   ~[dvlabel> dvlabel -c -e -o fig
  231   ~   ~This is dvlabel, Version 1.4
  232   ~   ~Specify table of contents of the DV tape
  233   ~   ~[Enter text and finish with single dot on blank line]:
  234   ~   ~* Table of contents
  235   ~   ~* This is line number one
  236   ~   ~* This is line number two
  237   ~   ~* This is line number three
  238   ~   ~* .
  239   ~   ~Specify time stamp of DV tape. This is typically
  240   ~   ~the last date that appears as time stamp in the
  241   ~   ~recorded tape. [Press enter to use the current date]
  242   ~   ~* Monday 29/12/2003
  243   ~   ~Specify title of the DV tape [Press enter to leave blank title]:
  244   ~   ~* Beavis and Butthead
  245   ~   ~Specify author of the DV tape [Press enter to leave blank]:
  246   ~   ~* Fredrik Jonsson
  247   ~   ~Specify address of author of the DV tape
  248   ~   ~[Enter text and finish with single dot on blank line]:
  249   ~   ~* Storgatan 77
  250   ~   ~* SE-47111 Sunne, Sweden
  251   ~   ~* .
  252   ~   ~Specify email of author of the DV tape [Press enter to leave blank]:
  253   ~   ~* hmv@@hotmail.com
  254   }
  255   \bigskip
  256   The generated DV label {\tt fig.eps} looks like this:
  257   \bigskip
  258   \centerline{\epsfxsize=62.56mm\epsfbox{fig.eps}}
  259   \vfill\eject
  260   \noindent
  261   In this example, the {\tt -c} command line option specifies that the program
  262   should compile the generated \TeX\ code, {\tt -e} that it also should attempt
  263   to generate the output as Encapsulated PostScript, and {\tt -o fig}
  264   that the generated files all should have the base name ``{\tt fig}'',
  265   that is to say, the program will use {\tt fig.tex} for the
  266   generated \TeX-code, {\tt fig.dvi}
  267   for the generated device-independent (DVI) output, and {\tt fig.eps} for
  268   the generated Encapsulated PostScript (EPS) image of the DV label.
  269   The command for invoking the \dvlabel\ program can equivalently be written in
  270   a more extensive form as {\tt dvlabel --compile --eps --outputfile fig}.
  271   
  272   The \TeX-code that the program generates (from which the Encapsulated
  273   PostScript subsequently is generated) is stored in the file {\tt fig.tex},
  274   which contains
  275   \bigskip
  276   {\obeylines\obeyspaces\tt
  277   ~   ~\% File: fig.tex
  278   ~   ~\% TeX code automatically generated by dvlabel, v.1.4,
  279   ~   ~\% Mon Dec 29 15:46:36 2003
  280   ~   ~\% Copyright (C) Fredrik Jonsson, 2003
  281   ~   ~\%
  282   ~   ~{\char'134}font{\char'134}eightcmssqeight=cmssq8
  283   ~   ~{\char'134}font{\char'134}tencmssqten=cmssq8 at 10 truept
  284   ~   ~{\char'134}font{\char'134}defaultfacefont=cmtt8
  285   ~   ~{\char'134}font{\char'134}defaultflapfont=cmtt8
  286   ~   ~{\char'134}def{\char'134}monthname{{\char'134}ifcase{\char'134}month\%
  287   ~   ~ {\char'134}or Jan{\char'134}or Feb{\char'134}or Mar{\char'134}or
  288        Apr{\char'134}or May{\char'134}or Jun\%
  289   ~   ~ {\char'134}or Jul{\char'134}or Aug{\char'134}or Sep{\char'134}or
  290        Oct{\char'134}or Nov{\char'134}or Dec\%
  291   ~   ~ {\char'134}fi}
  292   ~   ~{\char'134}def{\char'134}fullmonthname{{\char'134}ifcase{\char'134}month\%
  293   ~   ~ {\char'134}or January{\char'134}or February{\char'134}or
  294        March{\char'134}or April\%
  295   ~   ~ {\char'134}or May{\char'134}or June{\char'134}or July{\char'134}or
  296        August{\char'134}or September
  297   ~   ~ {\char'134}or October{\char'134}or November{\char'134}or
  298        December{\char'134}fi}
  299   ~   ~{\char'134}def{\char'134}today{{\char'134}fullmonthname{\char'134}space%
  300        {\char'134}number{\char'134}day,\%
  301   ~   ~  {\char'134}space{\char'134}number{\char'134}year}
  302   ~   ~{\char'134}def{\char'134}timestamp{Monday 29/12/2003}
  303   ~   ~{\char'134}def{\char'134}title{Beavis and Butthead}
  304   ~   ~{\char'134}def{\char'134}author{Fredrik Jonsson}
  305   ~   ~{\char'134}def{\char'134}email{hmv@@hotmail.com}
  306   ~   ~{\char'134}nopagenumbers
  307   ~   ~{\char'134}newdimen{\char'134}facewidth
  308   ~   ~{\char'134}newdimen{\char'134}faceheight
  309   ~   ~{\char'134}newdimen{\char'134}spineheight
  310   ~   ~{\char'134}newdimen{\char'134}flapheight
  311   ~   ~{\char'134}newdimen{\char'134}edgeseparation
  312   ~   ~{\char'134}facewidth=60mm
  313   ~   ~{\char'134}faceheight=40mm
  314   ~   ~{\char'134}spineheight=12mm
  315   ~   ~{\char'134}flapheight=20mm
  316   ~   ~{\char'134}edgeseparation=1pt
  317   ~   ~{\char'134}def{\char'134}boxit\#1{{\char'134}vbox{{\char'134}hrule%
  318        {\char'134}hbox{\%
  319   ~   ~  {\char'134}vrule{\char'134}kern1pt{\char'134}vbox{{\char'134}kern1pt\#1%
  320        {\char'134}kern1pt}\%
  321   ~   ~{\char'134}kern1pt{\char'134}vrule}{\char'134}hrule}}
  322   ~   ~{\char'134}parindent 0pt
  323   }
  324   \vfill\eject
  325   {\obeylines\obeyspaces\tt
  326   ~   ~
  327   ~   ~\% Define the outline of the face of the label
  328   ~   ~{\char'134}setbox1={\char'134}hbox to {\char'134}facewidth{{\%
  329   ~   ~  {\char'134}vbox to {\char'134}faceheight{\%
  330   ~   ~    {\char'134}hbox{{\char'134}defaultfacefont{\char'134}timestamp%
  331           {\char'134}hfil}\%
  332   ~   ~    {\char'134}vskip -3pt{\char'134}hbox{{\char'134}defaultfacefont
  333         Table of contents{\char'134}hfil}\%
  334   ~   ~    {\char'134}vskip -3pt{\char'134}hbox{{\char'134}defaultfacefont
  335         This is line number one{\char'134}hfil}\%
  336   ~   ~    {\char'134}vskip -3pt{\char'134}hbox{{\char'134}defaultfacefont
  337         This is line number two{\char'134}hfil}\%
  338   ~   ~    {\char'134}vskip -3pt{\char'134}hbox{{\char'134}defaultfacefont
  339         This is line number three{\char'134}hfil}\%
  340   ~   ~  {\char'134}vfil}}{\char'134}hfil}
  341   ~   ~
  342   ~   ~\% Define the outline of the spine of the label
  343   ~   ~{\char'134}setbox2={\char'134}hbox to {\char'134}facewidth{{\%
  344   ~   ~  {\char'134}vbox to {\char'134}spineheight{\%
  345   ~   ~    {\char'134}hbox{{\char'134}bf{\char'134}timestamp{\char'134}hfil}\%
  346   ~   ~    {\char'134}hbox{{\char'134}bf{\char'134}title{\char'134}hfil}\%
  347   ~   ~  {\char'134}vfil}}{\char'134}hfil}
  348   ~   ~
  349   ~   ~\% Define the outline of the flap of the label
  350   ~   ~{\char'134}setbox3={\char'134}hbox to {\char'134}facewidth{{\%
  351   ~   ~  {\char'134}vbox to {\char'134}flapheight{\%
  352   ~   ~    {\char'134}hbox{{\char'134}defaultflapfont Digital Video by
  353         {\char'134}author{\char'134}hfil}\%
  354   ~   ~    {\char'134}vskip -3pt{\char'134}hbox{{\char'134}defaultflapfont
  355         Storgatan 77{\char'134}hfil}\%
  356   ~   ~    {\char'134}vskip -3pt{\char'134}hbox{{\char'134}defaultflapfont
  357         SE-47111 Sunne, Sweden{\char'134}hfil}\%
  358   ~   ~    {\char'134}vskip -3pt{\char'134}hbox{{\char'134}defaultflapfont \%
  359   ~   ~      <{\char'134}email>{\char'134}hfil}\%
  360   ~   ~  {\char'134}vfil}}{\char'134}hfil}
  361   ~   ~
  362   ~   ~{\char'134}def{\char'134}dvlabel{{\char'134}boxit{{\char'134}boxit%
  363        {{\char'134}box1}\%
  364   ~   ~  {\char'134}vskip{\char'134}edgeseparation{\char'134}boxit%
  365        {{\char'134}box2}\%
  366   ~   ~  {\char'134}vskip{\char'134}edgeseparation{\char'134}%
  367         boxit{{\char'134}box3}}}
  368   ~   ~
  369   ~   ~{\char'134}dvlabel
  370   ~   ~
  371   ~   ~{\char'134}bye
  372   }
  373   \vfill\eject
  374   \noindent{\bf Example II:}
  375   Another way of using the program is in batch mode, where the input instead
  376   is read from a text file.
  377   In the following example, the file named {\tt fig.asc} contains the
  378   following text (compare with the interactive session on the previous pages):
  379   \bigskip
  380   {\obeyspaces\obeylines\tt
  381   ~   ~Table of contents
  382   ~   ~This is line number one
  383   ~   ~This is line number two
  384   ~   ~This is line number three
  385   ~   ~.
  386   ~   ~Monday 29/12/2003
  387   ~   ~Beavis and Butthead
  388   ~   ~Fredrik Jonsson
  389   ~   ~Storgatan 77
  390   ~   ~SE-47111 Sunne, Sweden
  391   ~   ~.
  392   ~   ~hmv@@hotmail.com
  393   }
  394   \bigskip
  395   \noindent
  396   When the \dvlabel\ program is launched with the above file specified as
  397   the input to read, via the command\footnote{$\dagger$}{In similar to
  398   the previous example, this command for invoking the \dvlabel\ program
  399   can similarly written in a more extensive form as {\tt dvlabel --compile
  400   --eps --inputfile fig.asc --outputfile fig}.}
  401   \bigskip
  402   {\obeyspaces\obeylines\tt
  403   ~   ~[dvlabel> dvlabel -c -e -i fig.asc -o fig
  404   }
  405   \bigskip
  406   \noindent
  407   the same output as in the previous example will be generated.
  408   
  409   @*The main program. Here follows the general outline of the main program.
  410   
  411   @c
  412   #include <time.h>
  413   #include <sys/time.h>
  414   #include <stdio.h>
  415   #include <stdarg.h>
  416   #include <stdlib.h>
  417   #include <string.h>
  418   #include <ctype.h>
  419   
  420   #define VERSION "1.6" /* Program revision */
  421   #define DEFAULT_DVIPSOPTS "-ta4 -D1200" /* Default DVIPS options */
  422   #define DEFAULT_LINETHICKNESS (0.5) /* Default line thickness in pt */
  423   #define DEFAULT_CROPLINETHICKNESS (0.15) /* Crop line thickness in pt */
  424   #define DEFAULT_EDGESEPARATION (1.0)
  425   #define MAXCHAR (128) /* Maximum allowed number of characters on each line */
  426   
  427   #define SUCCESS (0) /* Return code for successful program termination */
  428   #define FAILURE (1) /* Return code for unsuccessful program termination */
  429   
  430   #define INSTREAM (infile_specified?infile:stdin)
  431   #define OUTSTREAM (outfile_specified?outfile:stdout)
  432   
  433   #define log(...) log_printf(__func__, __VA_ARGS__)
  434   
  435   @<Global variables@>@;
  436   @<Subroutines@>@;
  437   
  438   int main(int argc, char *argv[])
  439   {
  440      @<Local variables@>@;
  441      @<Parse command line@>@;
  442      @<Display banner@>@;
  443      @<Open files for reading@>@;
  444      @<Open files for writing@>@;
  445      @<Save preamble source code@>@;
  446      num_labels=0;
  447      while (newlabel(INSTREAM)) {
  448         num_labels++;
  449         @<Scan text lines of one label from input stream@>@;
  450         if (num_labels==1) {
  451            if (generate_crop_marks) {
  452               @<Write vertical crop marks with width measure@>@;
  453               @<Write horizontal crop marks with height measure@>@;
  454            }
  455         }
  456         @<Save label source code@>@;
  457         if (num_labels==2) {
  458            if (generate_crop_marks) {
  459               @<Write horizontal crop marks with height measure@>@;
  460            }
  461         }
  462         if (num_labels==num_labels_per_page) {
  463            if (generate_crop_marks) {
  464               @<Write horizontal crop marks with height measure@>@;
  465               @<Write vertical crop marks with width measure@>@;
  466            }
  467            @<Close output page@>@;
  468            num_labels=0;
  469         }
  470      }
  471      @<Save closing source code@>@;
  472      @<Close files@>@;
  473      @<Compile source code@>@;
  474      return(SUCCESS);
  475   }
  476   
  477   @ Declaration of global variables. The only global variables allowed in
  478   my programs are |optarg|, which is the string of characters that specified
  479   the call from the command line, and |progname|, which simply is the string
  480   containing the name of the program, as it was invoked from the command line.
  481   
  482   @<Glob...@>=
  483      extern char *optarg;
  484      char *progname;
  485   
  486   @ Declarations of subroutines used by the program.
  487   
  488   @<Subroutines@>=
  489      @<Routine for logging and error messaging@>@;
  490      @<Routine for displaying help message@>@;
  491      @<Scan for beginning of new label@>@;
  492      @<Routine for removing preceding path of filenames@>@;
  493   
  494   @ The |void log_printf(const char *function_name,const char *format, ...)|
  495   routine writes formatted entries to standard output, displaying time and
  496   calling routine in a coherent manner. Notice that although the |log_printf()|
  497   routine is the one which performs the actual messaging, the |log()| macro
  498   (defined in the header file) is the preferred way of accessing this routine,
  499   as it provides a more compact notation and automatically takes care of supplying
  500   the reference to the name of the calling function.
  501   
  502   Also notice that the |const char| type of the last two input pointer arguments
  503   here is absolutely essential in order to pass strict pedantic compilation with
  504   GCC.
  505   
  506   The routine accepts two input parameters. First, |function_name| which should
  507   be the name of the calling function. This is to ensure that any displayed
  508   error messages are properly matched to the issuing routines. Notice, however,
  509   that the |log()| macro (which is the preferred way of displaying error messages)
  510   automatically takes care of supplying the proper function name.
  511   Second, |format|, which simply is the format and message string to be
  512   displayed, formatted in the \CEE-standard |printf()| or |fprintf()| syntax.
  513   
  514   @<Routine for logging and error messaging@>=
  515   void log_printf(const char *function_name, const char *format, ...) {
  516      va_list args;
  517      time_t time0;
  518      struct tm lt;
  519      struct timeval tv;
  520      char logentry[1024];
  521   
  522      gettimeofday(&tv, NULL);
  523      time(&time0);
  524      lt = *localtime(&time0);
  525      sprintf(logentry, "%02u%02u%02u %02u:%02u:%02u.%03d ",
  526         lt.tm_year-100, lt.tm_mon+1, lt.tm_mday,
  527         lt.tm_hour, lt.tm_min, lt.tm_sec, tv.tv_usec/1000);
  528      sprintf(logentry+strlen(logentry),"(%s) ",function_name);
  529      va_start(args, format); /* Initialize args by the |va_start()| macro */
  530      vsprintf(logentry+strlen(logentry), format, args);
  531      va_end(args); /* Terminate the use of args by the |va_end()| macro */
  532      sprintf(logentry+strlen(logentry), "\n"); /* Always append newline */
  533      fprintf(stdout, "%s", logentry);
  534      return;
  535   }
  536   
  537   @ Routines for displaying help message.
  538   
  539   @<Routine for displaying help message@>=
  540   @<Routine for displaying a single line of the help message@>@;
  541   void showsomehelp(void) {
  542     hl("Usage: %s [options]",progname);
  543     hl("When invoked without any command line options, this program enters");
  544     hl("interactive mode.");
  545     hl("Options:");
  546     hl(" -i, --inputfile <str>");
  547     hl("    Specifies the file where to read the label text strings, entered in");
  548     hl("    a format corresponding to the input order as would have been");
  549     hl("    entered in interactive mode.");
  550     hl(" -o, --outputfile <str>");
  551     hl("    Specifies the file where to save the generated TeX source code for");
  552     hl("    the label. whenever this option is omitted, the generated source");
  553     hl("    code will be written to standard terminal output instead. Notice");
  554     hl("    that the name specified using this option is used as the *base");
  555     hl("    name* for the generated output; this means that the TeX file");
  556     hl("    automatically will get .tex as suffix, the DVIfile .dvi, etc.");
  557     hl("    For example, if you want to have your TeX output stored into a file");
  558     hl("    named, say, 'foo.tex', just specify '-o foo'.");
  559     hl(" -H, --headline");
  560     hl("    Toggle display of generation time and input source in page header");
  561     hl("    of the generated TeX code. Default: off");
  562     hl(" -C, --cropmarks");
  563     hl("    Toggle display of crop marks (alignment marks) in the generated TeX");
  564     hl("    code. Default: off");
  565     hl(" -t, --linethick <f>");
  566     hl("    Use linethickness of <f> typographic points in generating the boxes");
  567     hl("    of the label. (One point, or pt, equals to 1/72.27 inch.)");
  568     hl(" -s, --edgeseparation <f>");
  569     hl("    Insert extra space of <f> typographic points between the text boxes");
  570     hl("    at the folded edges of the label. This is useful when, for example,");
  571     hl("    thick paper is used. By changing the line thickness, the internal");
  572     hl("    margins of the label are also changed, since the inner edge-to-edge");
  573     hl("    distance between the lines of the inner and outer boxes are linked");
  574     hl("    to be twice the value of the line thickness. The correction of");
  575     hl("    inner bounding boxes of the label text is automatically adjusted so");
  576     hl("    as to ensure that the overall outer dimensions of the label are");
  577     hl("    unchanged.");
  578     hl(" -c, --compile");
  579     hl("    Try to compile the generated TeX code. This requires DVIPS to be");
  580     hl("    installed on your system, see www.radicaleye.com for further info.");
  581     hl(" -e, --eps");
  582     hl("    When compiling the generated TeX code, generate Encapsulated");
  583     hl("    PostScript (EPS) instead of the default regular PostScript.");
  584     hl(" -d, --dvipsopts <str>");
  585     hl("    When compiling the generated TeX code, use <str> as options to be");
  586     hl("    supplied to DVIPS. In order to parse for an arbitrary number of");
  587     hl("    DVIPS options at the command line, it is important to enclose the");
  588     hl("    list of DVIPS options by quotes. Hence, for example, to force DVIPS");
  589     hl("    to generate output pages of US letter format and at a resolution of");
  590     hl("    720 dpi one could invoke DVLABEL with");
  591     hl("          dvlabel --dvipsopts \"-tletter -D720\"");
  592     hl("    The quotes are only necessary if the number of DVIPS options are");
  593     hl("    two or more. Default: -D1200 -ta4 (1200 DPI on A4 paper).");
  594     hl(" -v, --verbose");
  595     hl("    Toggle verbose mode. Default: off");
  596     hl(" -h, --help");
  597     hl("    Display this help message and exit clean.");
  598     hl("\nCopyright (C) 2003-2011 Fredrik Jonsson <http://jonsson.eu>");
  599   }
  600   
  601   @ In order to simplify the messaging, the |hl(const char *format, ...)| routine
  602   acts as a simple front-end merely for compactifying the code by successive
  603   calls to |hl(...)| rather than the full |fprintf(stderr, ...)|, still
  604   maintaining all the functionality of string formatting in the regular
  605   |printf()| or |fprintf()| syntax.
  606   
  607   @<Routine for displaying a single line of the help message@>=
  608   void hl(const char *format, ...) {
  609      va_list args;
  610      char line[1024];
  611   
  612      va_start(args, format); /* Initialize args by the |va_start()| macro */
  613      vsprintf(line, format, args);
  614      va_end(args); /* Terminate the use of args by the |va_end()| macro */
  615      sprintf(line+strlen(line), "\n"); /* Always append newline */
  616      fprintf(stdout, "%s", line);
  617      return;
  618   }
  619   
  620   @ Scan the input stream for a statement on what to do next, that is to say,
  621   either to start generating a new label (if the character `n' is present, in
  622   which case the |newlabel| routine returns 1) or quit the program (if the
  623   character `q' is present, in which case the |newlabel| routine returns 0).
  624   The |newlabel| routine also takes care of scanning away any trailing blanks
  625   or other characters from the input stream until a carriage return character
  626   is found, also removing this before return.
  627   
  628   @<Scan for beginning of new label@>=
  629   short newlabel(FILE *instream) {
  630      char ch;
  631      fprintf(stdout,"Create new label record or quit?\n");
  632      fprintf(stdout,"['n'=new label / 'q'=quit]:\n");
  633      fprintf(stdout,"**");
  634      while((ch=fgetc(instream))==' '); /* get rid of leading blanks */
  635      if (ch=='n') {
  636         while((ch=fgetc(instream))!='\n'); /* get rid of trailing characters */
  637         return(1);
  638      } else if (ch=='q') {
  639         while((ch=fgetc(instream))!='\n'); /* get rid of trailing characters */
  640         return(0);
  641      } else {
  642         log("%s: Error: Unrecognized input stream control character '%c'.\n",
  643            progname,ch);
  644         exit(FAILURE);
  645      }
  646   }
  647   
  648   @ Routines for removing preceding path of filenames.
  649   In this block all routines related to removing preceding path strings go.
  650   Not really fancy programming, and no contribution to any increase of numerical
  651   efficiency or precision; just for the sake of keeping a tidy terminal output
  652   of the program. The |strip_away_path()| routine is typically called when
  653   initializing the program name string |progname| from the command line string
  654   |argv[0]|, and is typically located in the blocks related to parsing of the
  655   command line options.
  656   The |strip_away_path()| routine takes a character string |filename| as
  657   argument, and returns a pointer to the same string but without any
  658   preceding path segments.
  659   
  660   @<Routine for removing preceding path of filenames@>=
  661   @<Routine for checking for a valid path character@>@;
  662   char *strip_away_path(char filename[]) {
  663      int j,k=0;
  664      while (pathcharacter(filename[k])) k++;
  665      j=(--k); /* this is the uppermost index of the full path+file string */
  666      while (isalnum((int)(filename[j]))) j--;
  667      j++; /* this is the lowermost index of the stripped file name */
  668      return(&filename[j]);
  669   }
  670   
  671   @ In this program, valid path characters are any alphanumeric character or
  672   `\.{.}', `\.{/}', `\.{\\}', `\.{\_}', `\.{-}', or `\.{+}'.
  673   
  674   @<Routine for checking for a valid path character@>=
  675   short pathcharacter(int ch) {
  676      return(isalnum(ch)||(ch=='.')||(ch=='/')||(ch=='\\')||(ch=='_')||
  677          (ch=='-')||(ch=='+'));
  678   }
  679   
  680   @*Declaration of local variables of the main program.
  681   Here |num_labels| is a counter that is used for determining whenever a page
  682   brake in the generated \TeX\ code is to appear, in order to give a nice output
  683   with a $[3\times1]$ array of labels.
  684   
  685   @<Local variables@>=
  686      time_t now=time(NULL);
  687      long j,k,n,num_address_lines,num_toc_lines,num_labels,num_labels_per_page=4;
  688      int no_arg,tmpch;
  689      FILE *infile=NULL,*outfile=NULL;
  690      char inputfilename[MAXCHAR]="",outputfilename[MAXCHAR]="",tmpstr[MAXCHAR];
  691      char dvipsopts[MAXCHAR]=DEFAULT_DVIPSOPTS;
  692      char timestamp[MAXCHAR]="\today",title[MAXCHAR]="";
  693      char author[MAXCHAR]="",email[MAXCHAR]="";
  694      char address[10*MAXCHAR]="",toc[50*MAXCHAR]="";
  695      short done,verbose=0,compile=0,eps_output=0;
  696      short headline=1,generate_crop_marks=1;
  697      short infile_specified=0,outfile_specified=0,dvipsopts_specified=0;
  698      float linethickness=DEFAULT_LINETHICKNESS;
  699      float clthick=DEFAULT_CROPLINETHICKNESS;
  700      float edgeseparation=DEFAULT_EDGESEPARATION;
  701      float facewidth,faceheight,spineheight,flapheight;
  702      float ifacewidth,ifaceheight,ispineheight,iflapheight;
  703   
  704   
  705   @*Parsing command line options. All input parameters are passed to the
  706   program through command line options and arguments to the program.
  707   The syntax of command line options is listed whenever the program is invoked
  708   with the {\tt --help} option at startup, or whenever an error occurs in the
  709   input.
  710   
  711   @<Parse command line@>=
  712   {
  713      progname=strip_away_path(argv[0]);
  714      no_arg=argc;
  715      while(--argc) {
  716         if(!strcmp(argv[no_arg-argc],"-o") ||
  717            !strcmp(argv[no_arg-argc],"--outputfile")) {
  718            --argc;
  719            strcpy(outputfilename,argv[no_arg-argc]);
  720            outfile_specified=1;
  721         } else if(!strcmp(argv[no_arg-argc],"-i") ||
  722                   !strcmp(argv[no_arg-argc],"--inputfile")) {
  723            --argc;
  724            strcpy(inputfilename,argv[no_arg-argc]);
  725            infile_specified=1;
  726         } else if(!strcmp(argv[no_arg-argc],"-v") ||
  727                   !strcmp(argv[no_arg-argc],"--verbose")) {
  728            verbose=(verbose?0:1);
  729         } else if(!strcmp(argv[no_arg-argc],"-h") ||
  730                   !strcmp(argv[no_arg-argc],"--help")) {
  731            showsomehelp();
  732            exit(SUCCESS);
  733         } else if(!strcmp(argv[no_arg-argc],"-H") ||
  734                   !strcmp(argv[no_arg-argc],"--headline")) {
  735            headline=(headline?0:1);
  736         } else if(!strcmp(argv[no_arg-argc],"-C") ||
  737                   !strcmp(argv[no_arg-argc],"--cropmarks")) {
  738            generate_crop_marks=(generate_crop_marks?0:1);
  739         } else if(!strcmp(argv[no_arg-argc],"-t") ||
  740                   !strcmp(argv[no_arg-argc],"--linethick")) {
  741            --argc;
  742            if (!sscanf(argv[no_arg-argc],"%f",&linethickness)) {
  743               log("Error in linethickness argument.");
  744               exit(1);
  745            }
  746         } else if(!strcmp(argv[no_arg-argc],"-s") ||
  747                   !strcmp(argv[no_arg-argc],"--edgeseparation")) {
  748            --argc;
  749            if (!sscanf(argv[no_arg-argc],"%f",&edgeseparation)) {
  750               log("Error in edgeseparation argument.");
  751               exit(1);
  752            }
  753         } else if(!strcmp(argv[no_arg-argc],"-c") ||
  754                   !strcmp(argv[no_arg-argc],"--compile")) {
  755            compile=(compile?0:1);
  756         } else if(!strcmp(argv[no_arg-argc],"-e") ||
  757                   !strcmp(argv[no_arg-argc],"--eps")) {
  758            eps_output=(eps_output?0:1);
  759         } else if(!strcmp(argv[no_arg-argc],"-d") ||
  760                   !strcmp(argv[no_arg-argc],"--dvipsopts")) {
  761            --argc;
  762            strcpy(dvipsopts,argv[no_arg-argc]);
  763            dvipsopts_specified=1;
  764         } else {
  765            log("Error: Unknown option '%s'.",argv[no_arg-argc]);
  766            showsomehelp();
  767            exit(FAILURE);
  768         }
  769      }
  770      if (verbose && !outfile_specified) {
  771         fprintf(stdout,
  772            "You have specified verbose mode without any specification of\n"
  773            "a file where to save the generated TeX source code. This means\n"
  774            "that any program comments that appear, due to the verbose mode,\n"
  775            "will be mixed with the source code. It is highly recommended that\n"
  776            "you either turn off verbose mode or specify a file where to save\n"
  777            "the generated output (using the -o or --outputfile option).\n");
  778         fprintf(stdout,
  779            "In order to make a clean output, the TeX code is separately\n"
  780            "enclosed in the blocks below.\n");
  781      }
  782      if (verbose && dvipsopts_specified) {
  783         fprintf(stdout,"Specified options for later use with DVIPS: ");
  784         fprintf(stdout,"%s\n",dvipsopts);
  785      }
  786   }
  787   
  788   @ Display a banner at start-up of the program.
  789   
  790   @<Display banner@>=
  791   {
  792      fprintf(stdout,"This is %s, Version %s\n",progname,VERSION);
  793   }
  794   
  795   @*Opening and closing files for data output.
  796   
  797   @ Open files for reading. In order to read the text to typeset from an external
  798   file rather than the default standard input stream {\tt stdin}, the name of the
  799   input file is specified with the {\tt -i} or {\tt --inputfile} command line
  800   options.
  801   If the filename as specified on the command line does not exist, then the
  802   program will instead try to open a file with the suffix {\tt .dvl} concatenated
  803   to the name. This way, the program will accept short-hand filenames as well, in
  804   a way analogous to the input syntax rules of, for example, the \TeX\ program.
  805   If no input file can be opened, an error message is displayed and the program
  806   will exit with return value |FAILURE|.
  807   
  808   @<Open files for reading@>=
  809   {
  810      if (infile_specified) {
  811         if ((infile=fopen(inputfilename,"r")) == NULL) {
  812            if ((infile=fopen(strcat(inputfilename,".dvl"),"r")) == NULL) {
  813               log("Could not open file %s for reading!",inputfilename);
  814               exit(FAILURE);
  815            }
  816         }
  817         fseek(infile,0L,SEEK_SET);
  818         if (verbose) {
  819            log("Opened input file %s for reading.",inputfilename);
  820         }
  821      } else {
  822         if (verbose)
  823            log("No input filename specified (Entering interactive mode).");
  824      }
  825   }
  826   
  827   @ Open files for writing.
  828   
  829   @<Open files for writing@>=
  830   {
  831      if (outfile_specified) {
  832         sprintf(tmpstr,"%s.tex",outputfilename);
  833         if ((outfile=fopen(tmpstr,"w")) == NULL) {
  834            log("Could not open file %s for writing!",tmpstr);
  835            exit(FAILURE);
  836         }
  837         fseek(outfile,0L,SEEK_SET);
  838         if (verbose) {
  839            log("Opened output file %s for writing.",outputfilename);
  840         }
  841      } else {
  842         if (verbose) {
  843            log("No output filename specified.");
  844            log("Will write generated TeX output to standard terminal output.");
  845         }
  846      }
  847   }
  848   
  849   @ Close all open files.
  850   
  851   @<Close files@>=
  852   {
  853      if (infile_specified) fclose(infile);
  854      if (outfile_specified) fclose(outfile);
  855   }
  856   
  857   @*Reading input as supplied by the user.
  858   
  859   @ Parsing the input as supplied by the user. When reading the input, the
  860   \dvlabel\ program makes use of either the |stdin| stream (in the case of
  861   interactive mode), or the file pointed out by the |infile| pointer (in the
  862   case of processing of an input text file).
  863   In the latter case, the syntax of the supplied file is identical to the
  864   syntax as if operating the program in interactive mode, with every newline
  865   character ({\tt /n}) interpreted as an end-of-line of a corresponding
  866   interactive input.
  867   
  868   Example: [TO BE INSERTED]
  869   
  870   As the individual lines of text generally contain different number of
  871   characters, the feedline character {\tt /n} of standard \CEE\ is throughout
  872   the program used to keep track of the end of line. (This is more convenient
  873   than keeping track of the indvidual line widths in, for example, and array
  874   of integers.)
  875   
  876   @<Scan text lines of one label from input stream@>=
  877   {
  878      @<Read table of contents@>@;
  879      @<Read time stamp@>@;
  880      @<Read title@>@;
  881      @<Read author name@>@;
  882      @<Read address@>@;
  883      @<Read email address@>@;
  884   }
  885   
  886   @ Parse for the table of contents of the tape.
  887   The syntax for specifying the table of contents is similar to that of the
  888   address, with arbitrary number of lines of text. The input is ended by
  889   a single dot on a new line, in similar to the way of entering, for example,
  890   email messages in terminal mode using the basic engine of {\tt sendmail} on
  891   regular UNIX and Linux systems.
  892   
  893   @<Read table of contents@>=
  894   {
  895      fprintf(stdout,"Specify table of contents of the DV tape\n");
  896      fprintf(stdout,"[Enter text and finish with single dot on blank line]:\n");
  897      done=0;
  898      n=0;
  899      num_toc_lines=0;
  900      while (!done) {
  901         fprintf(stdout,"**");
  902         while ((tmpch=fgetc(INSTREAM))==' '); /* Get rid of leading blanks */
  903         ungetc(tmpch,INSTREAM);
  904         k=0;
  905         while ((tmpstr[k++]=fgetc(INSTREAM))!='\n'); /* Read line */
  906         if (k>1) { /* If more text than just spaces and a linefeed character */
  907            if ((tmpstr[0]=='.')&&(tmpstr[1]=='\n')) {
  908               done=1;
  909            } else {
  910               for (j=0;j<k;j++) toc[n+j]=tmpstr[j];
  911               if (1==0) toc[n+j]='\n';
  912               n=n+j; /* Keep track of last index of the |toc| array */
  913               num_toc_lines++;
  914            }
  915         } else { /* If just spaces and a linefeed character */
  916            toc[n]='\n'; /* Blank line of table-of-contents field */
  917         }
  918      }
  919      if (verbose) {
  920         fprintf (stdout,"%s: Counted %ld number of table-of-contents lines.\n",
  921            progname,num_toc_lines);
  922         fprintf(stdout,"Table of contents:\n");
  923         n=0;
  924         for (k=1;k<=num_toc_lines;k++) {
  925            for (j=n;toc[j]!='\n';j++) fprintf(stdout,"%c",toc[j]);
  926            fprintf(stdout,"\n");
  927            n=j+1;
  928         }
  929      }
  930   }
  931   
  932   @ Parse for the time stamp to be used.
  933   
  934   @<Read time stamp@>=
  935   {
  936      fprintf(stdout,"Specify time stamp of DV tape. This is typically\n");
  937      fprintf(stdout,"the last date that appears as time stamp in the\n");
  938      fprintf(stdout,"recorded tape. [Press enter to use the current date]\n");
  939      fprintf(stdout,"**");
  940      while ((tmpch=fgetc(INSTREAM))==' '); /* Get rid of leading blank spaces */
  941      ungetc(tmpch,INSTREAM);
  942      k=0;
  943      while ((tmpstr[k++]=fgetc(INSTREAM))!='\n'); /* Read line */
  944      if (k>1) /* If more text than just spaces and a linefeed character */
  945         for (j=0;j<k;j++) timestamp[j]=tmpstr[j];
  946      else /* If just spaces and a linefeed character */
  947         for (j=0;j<7;j++) timestamp[j]="\\today\n"[j];
  948      if (verbose) {
  949         fprintf(stdout,"Time stamp: ");
  950         for (j=0;timestamp[j]!='\n';j++) fprintf(stdout,"%c",timestamp[j]);
  951         fprintf(stdout,"\n");
  952      }
  953   }
  954   
  955   @ Parse for the title to be used.
  956   
  957   @<Read title@>=
  958   {
  959      fprintf(stdout,
  960        "Specify title of the DV tape [Press enter to leave blank title]:\n");
  961      fprintf(stdout,"**");
  962      while ((tmpch=fgetc(INSTREAM))==' '); /* Get rid of leading blank spaces */
  963      ungetc(tmpch,INSTREAM);
  964      k=0;
  965      while ((tmpstr[k++]=fgetc(INSTREAM))!='\n'); /* Read line */
  966      if (k>1) /* If more text than just spaces and a linefeed character */
  967         for (j=0;j<k;j++) title[j]=tmpstr[j];
  968      else /* If just spaces and a linefeed character */
  969         title[0]='\n'; /* Blank title */
  970      if (verbose) {
  971         fprintf(stdout,"Title: ");
  972         for (j=0;title[j]!='\n';j++) fprintf(stdout,"%c",title[j]);
  973         fprintf(stdout,"\n");
  974      }
  975   }
  976   
  977   @ Parse for the author name to be used.
  978   
  979   @<Read author name@>=
  980   {
  981      fprintf(stdout,
  982        "Specify author of the DV tape [Press enter to leave blank]:\n");
  983      fprintf(stdout,"**");
  984      while ((tmpch=fgetc(INSTREAM))==' '); /* Get rid of leading blank spaces */
  985      ungetc(tmpch,INSTREAM);
  986      k=0;
  987      while ((tmpstr[k++]=fgetc(INSTREAM))!='\n'); /* Read line */
  988      if (k>1) /* If more text than just spaces and a linefeed character */
  989         for (j=0;j<k;j++) author[j]=tmpstr[j];
  990      else /* If just spaces and a linefeed character */
  991         author[0]='\n'; /* Blank author field */
  992      if (verbose) {
  993         fprintf(stdout,"Author: ");
  994         for (j=0;author[j]!='\n';j++) fprintf(stdout,"%c",author[j]);
  995         fprintf(stdout,"\n");
  996      }
  997   }
  998   
  999   @ Parse for the address to be used.
 1000   The syntax for specifying the address is similar to that of the table of
 1001   contents, with arbitrary number of lines of text. The input is ended by
 1002   a single dot on a new line, in similar to the way of entering, for example,
 1003   email messages in terminal mode using the basic engine of {\tt sendmail} on
 1004   regular UNIX and Linux systems.
 1005   
 1006   @<Read address@>=
 1007   {
 1008      fprintf(stdout,"Specify address of author of the DV tape\n");
 1009      fprintf(stdout,"[Enter text and finish with single dot on blank line]:\n");
 1010      fprintf(stdout,"**");
 1011      done=0;
 1012      n=0;
 1013      num_address_lines=0;
 1014      while (!done) {
 1015         while ((tmpch=fgetc(INSTREAM))==' '); /* Get rid of leading spaces */
 1016         ungetc(tmpch,INSTREAM);
 1017         k=0;
 1018         while ((tmpstr[k++]=fgetc(INSTREAM))!='\n'); /* Read line */
 1019         if (k>1) { /* If more text than just spaces and a linefeed character */
 1020            if ((tmpstr[0]=='.')&&(tmpstr[1]=='\n')) {
 1021               done=1;
 1022            } else {
 1023               for (j=0;j<k;j++) address[n+j]=tmpstr[j];
 1024               if (1==0) address[n+j]='\n';
 1025               n=n+j; /* Keep track of last index of the |address| array */
 1026               num_address_lines++;
 1027            }
 1028         } else { /* If just spaces and a linefeed character */
 1029            address[n]='\n'; /* Blank line of address field */
 1030         }
 1031         fprintf(stdout,"**");
 1032      }
 1033      if (verbose) {
 1034         fprintf (stdout,"%s: Counted %ld address lines.\n",
 1035            progname,num_address_lines);
 1036         fprintf(stdout,"Address:\n");
 1037         n=0;
 1038         for (k=1;k<=num_address_lines;k++) {
 1039            for (j=n;address[j]!='\n';j++) fprintf(stdout,"%c",address[j]);
 1040            fprintf(stdout,"\n");
 1041            n=j+1;
 1042         }
 1043      }
 1044   }
 1045   
 1046   @ Parse for the email address to be used.
 1047   
 1048   @<Read email address@>=
 1049   {
 1050      fprintf(stdout,
 1051        "Specify email of author of the DV tape [Press enter to leave blank]:\n");
 1052      fprintf(stdout,"**");
 1053      while ((tmpch=fgetc(INSTREAM))==' '); /* Get rid of leading blank spaces */
 1054      ungetc(tmpch,INSTREAM);
 1055      k=0;
 1056      while ((tmpstr[k++]=fgetc(INSTREAM))!='\n'); /* Read line */
 1057      if (k>1) /* If more text than just spaces and a linefeed character */
 1058         for (j=0;j<k;j++) email[j]=tmpstr[j];
 1059      else /* If just spaces and a linefeed character */
 1060         email[0]='\n'; /* Blank email field */
 1061      if (verbose) {
 1062         fprintf(stdout,"Email: ");
 1063         for (j=0;email[j]!='\n';j++) fprintf(stdout,"%c",email[j]);
 1064         fprintf(stdout,"\n");
 1065      }
 1066   }
 1067   
 1068   @ Generating the preamble of output \TeX\ source code for the labels.
 1069   The physical outer of the Mini Digital Label dimensions are based on the inset
 1070   of TDK cassettes, with |flapheight| of 14.5~mm (41.3~pt), spineheight of
 1071   12.5~mm (35.6~pt), |faceheight| of 47~mm (133.7~pt), and |facewidth| of
 1072   67~mm (190.6~pt), hence summing up to overall outer dimensions of
 1073   $190.6\times210.6$~pt of the label.
 1074   
 1075   @<Save preamble source code@>=
 1076   {
 1077      facewidth=190.6+3.0*72.27/25.4;
 1078      faceheight=133.7;
 1079      spineheight=35.6;
 1080      flapheight=41.3;
 1081      ifacewidth=facewidth-14.0*linethickness;
 1082      ifaceheight=faceheight-11.0*linethickness-0.5*edgeseparation;
 1083      ispineheight=spineheight-8.0*linethickness-edgeseparation;
 1084      iflapheight=flapheight-11.0*linethickness-0.5*edgeseparation;
 1085      if (!outfile_specified)
 1086         fprintf(OUTSTREAM,"%%-------- TEX CODE BEGINS HERE -----------------\n");
 1087      fprintf(OUTSTREAM,"%% File: %s.tex\n",outputfilename);
 1088      fprintf(OUTSTREAM,"%% TeX code generated by %s, v.%s, %s",
 1089         progname,VERSION,ctime(&now));
 1090      fprintf(OUTSTREAM,"%% Copyright (C) Fredrik Jonsson, 2003-2005\n%%\n");
 1091      fprintf(OUTSTREAM,"\\hoffset=-35pt\\voffset=-25pt\n");
 1092      fprintf(OUTSTREAM,"\\hsize=175mm\\vsize=254mm\n");
 1093      fprintf(OUTSTREAM,"\\font\\eightcmssqeight=cmssq8\n");
 1094      fprintf(OUTSTREAM,"\\font\\sevencmtt=cmtt7\n");
 1095      fprintf(OUTSTREAM,"\\font\\tencmssqten=cmssq8 at 10 truept\n");
 1096      fprintf(OUTSTREAM,"\\font\\deffacefont=cmr7\n");
 1097      fprintf(OUTSTREAM,"\\font\\deftimestampfont=cmtt8 at 7 truept\n");
 1098      fprintf(OUTSTREAM,"\\font\\defspinefont=cmr9\n");
 1099      fprintf(OUTSTREAM,"\\font\\defflapfont=cmr7\n");
 1100      fprintf(OUTSTREAM,"\\def\\monthname{\\ifcase\\month%%\n");
 1101      fprintf(OUTSTREAM," \\or Jan\\or Feb\\or Mar\\or Apr\\or May\\or Jun%%\n");
 1102      fprintf(OUTSTREAM," \\or Jul\\or Aug\\or Sep\\or Oct\\or Nov\\or Dec%%\n");
 1103      fprintf(OUTSTREAM," \\fi}\n");
 1104      fprintf(OUTSTREAM,"\\def\\fullmonthname{\\ifcase\\month%%\n");
 1105      fprintf(OUTSTREAM," \\or January\\or February\\or March\\or April%%\n");
 1106      fprintf(OUTSTREAM," \\or May\\or June\\or July\\or August\\or September\n");
 1107      fprintf(OUTSTREAM," \\or October\\or November\\or December\\fi}\n");
 1108      fprintf(OUTSTREAM,"\\def\\today{\\fullmonthname\\space\\number\\day,%%\n");
 1109      fprintf(OUTSTREAM,"  \\space\\number\\year}\n");
 1110      fprintf(OUTSTREAM,"\\def\\dvby{Digital Video by\\ }\n");
 1111      fprintf(OUTSTREAM,"\\parindent 0pt\n");
 1112      fprintf(OUTSTREAM,"\\newdimen\\facewidth\n");
 1113      fprintf(OUTSTREAM,"\\newdimen\\faceheight\n");
 1114      fprintf(OUTSTREAM,"\\newdimen\\spineheight\n");
 1115      fprintf(OUTSTREAM,"\\newdimen\\flapheight\n");
 1116      fprintf(OUTSTREAM,"\\newdimen\\linethick\n");
 1117      fprintf(OUTSTREAM,"\\newdimen\\spacethick\n");
 1118      fprintf(OUTSTREAM,"\\newdimen\\edgeseparation\n");
 1119      fprintf(OUTSTREAM,"\\newdimen\\cropthick\n");
 1120      fprintf(OUTSTREAM,"\\facewidth=%1.3fpt\n",facewidth);
 1121      fprintf(OUTSTREAM,"\\faceheight=%1.3fpt\n",faceheight);
 1122      fprintf(OUTSTREAM,"\\spineheight=%1.3fpt\n",spineheight);
 1123      fprintf(OUTSTREAM,"\\flapheight=%1.3fpt\n",flapheight);
 1124      fprintf(OUTSTREAM,"\\linethick=%1.3fpt\n",linethickness);
 1125      fprintf(OUTSTREAM,"\\spacethick=%1.3fpt\n",2.0*linethickness);
 1126      fprintf(OUTSTREAM,"\\edgeseparation=%1.3fpt\n",edgeseparation);
 1127      fprintf(OUTSTREAM,"\\cropthick=%1.3fpt\n",clthick);
 1128      if (headline) {
 1129         fprintf(OUTSTREAM,"\\headline={\\hfill{\\tt dvlabel output");
 1130         fprintf(OUTSTREAM," %s",ctime(&now));
 1131         fprintf(OUTSTREAM," [%s]}}\n",(infile_specified?inputfilename:"stdin"));
 1132         fprintf(OUTSTREAM,"\\footline={\\hfill\\folio\\hfill}\n");
 1133      } else {
 1134         fprintf(OUTSTREAM,"\\headline={\\hfil}\n");
 1135         fprintf(OUTSTREAM,"\\nopagenumbers\n");
 1136      }
 1137      fprintf(OUTSTREAM,"\\def\\boxit#1{\\vbox{\\hrule height\\linethick%%\n");
 1138      fprintf(OUTSTREAM,"  \\hbox{\\vrule width\\linethick\\kern\\spacethick%%\n");
 1139      fprintf(OUTSTREAM,"  \\vbox{\\kern\\spacethick#1\\kern\\spacethick}%%\n");
 1140      fprintf(OUTSTREAM,"  \\kern\\spacethick\\vrule width\\linethick}%%\n");
 1141      fprintf(OUTSTREAM,"  \\hrule height\\linethick}}%%\n");
 1142   }
 1143   
 1144   @ Generating the output \TeX\ source code for the labels.
 1145   
 1146   @<Save label source code@>=
 1147   {
 1148      fprintf(OUTSTREAM,"\\def\\timestamp{");
 1149      for (j=0;timestamp[j]!='\n';j++) fprintf(OUTSTREAM,"%c",timestamp[j]);
 1150      fprintf(OUTSTREAM,"}%%\n");
 1151      fprintf(OUTSTREAM,"\\def\\title{");
 1152      for (j=0;title[j]!='\n';j++) fprintf(OUTSTREAM,"%c",title[j]);
 1153      fprintf(OUTSTREAM,"}%%\n");
 1154      fprintf(OUTSTREAM,"\\def\\author{");
 1155      for (j=0;author[j]!='\n';j++) fprintf(OUTSTREAM,"%c",author[j]);
 1156      fprintf(OUTSTREAM,"}%%\n");
 1157      fprintf(OUTSTREAM,"\\def\\email{");
 1158      for (j=0;email[j]!='\n';j++) fprintf(OUTSTREAM,"%c",email[j]);
 1159      fprintf(OUTSTREAM,"}%%\n");
 1160      fprintf(OUTSTREAM,"%% Define the outline of the face of the label\n");
 1161      fprintf(OUTSTREAM,"\\setbox1=\\hbox to %1.3fpt{{%%\n",ifacewidth);
 1162      fprintf(OUTSTREAM,"  \\vbox to \\faceheight{%%\n");
 1163      fprintf(OUTSTREAM,"    \\hbox{\\deffacefont\\timestamp\\hfil}%%\n");
 1164      n=0;
 1165      for (k=1;k<=num_toc_lines;k++) {
 1166         fprintf(OUTSTREAM,"    \\vskip -3pt\\hbox{\\deffacefont ");
 1167         for (j=n;toc[j]!='\n';j++) fprintf(OUTSTREAM,"%c",toc[j]);
 1168         fprintf(OUTSTREAM,"\\hfil}%%\n");
 1169         n=j+1;
 1170      }
 1171      fprintf(OUTSTREAM,"  \\vfil}}\\hfil}%%\n");
 1172      fprintf(OUTSTREAM,"%% Define the outline of the spine of the label\n");
 1173      fprintf(OUTSTREAM,"\\setbox2=\\hbox to %1.3fpt{{%%\n",ifacewidth);
 1174      fprintf(OUTSTREAM,"  \\vbox to %1.3fpt{%%\n",ispineheight);
 1175      fprintf(OUTSTREAM,"    \\hbox{\\deftimestampfont\\timestamp\\hfil}%%\n");
 1176      fprintf(OUTSTREAM,"    \\hbox{\\defspinefont\\title\\hfil}%%\n");
 1177      fprintf(OUTSTREAM,"  \\vfil}}\\hfil}%%\n");
 1178      fprintf(OUTSTREAM,"%% Define the outline of the flap of the label\n");
 1179      fprintf(OUTSTREAM,"\\setbox3=\\hbox to %1.3fpt{{%%\n",ifacewidth);
 1180      fprintf(OUTSTREAM,"  \\vbox to %1.3fpt{%%\n",iflapheight);
 1181      fprintf(OUTSTREAM,"    \\hbox{\\defflapfont\\dvby\\author\\hfil}%%\n");
 1182      n=0;
 1183      for (k=1;k<=num_address_lines;k++) {
 1184         fprintf(OUTSTREAM,"    \\vskip -3pt\\hbox{\\defflapfont ");
 1185         for (j=n;address[j]!='\n';j++) fprintf(OUTSTREAM,"%c",address[j]);
 1186         fprintf(OUTSTREAM,"\\hfil}\n");
 1187         n=j+1;
 1188      }
 1189      fprintf(OUTSTREAM,"    \\vskip -3pt\\hbox{\\defflapfont\\email\\hfil}%%\n");
 1190      fprintf(OUTSTREAM,"  \\vfil}}\\hfil}%%\n");
 1191      fprintf(OUTSTREAM,"\\def\\dvlabel{\\hskip\\linethick\\boxit{%%\n");
 1192      fprintf(OUTSTREAM,"  \\boxit{\\box1}\\vskip\\edgeseparation%%\n");
 1193      fprintf(OUTSTREAM,"  \\boxit{\\box2}\\vskip\\edgeseparation%%\n");
 1194      fprintf(OUTSTREAM,"  \\boxit{\\box3}}\\hskip\\linethick}%%\n");
 1195      if ((num_labels==1)||(num_labels==3)) fprintf(OUTSTREAM,"\\hskip %1.3fpt",
 1196         (20.0));
 1197      fprintf(OUTSTREAM,"\\dvlabel\n");
 1198      if ((num_labels==2)||(num_labels==4)||(num_labels==6)) {
 1199         fprintf(OUTSTREAM,"\\par\\nointerlineskip\n");
 1200      }
 1201   }
 1202   
 1203   @ Close one page of output, with each page containing |num_labels_per_page|
 1204   labels, and write any preamble for initialization of a new page to the output
 1205   stream.
 1206   
 1207   @<Close output page@>=
 1208   {
 1209      fprintf(OUTSTREAM,"\\vfill\\eject\n");
 1210   }
 1211   
 1212   @ Before writing the first row of labels to the page output, save the vertical
 1213   crop marks to be used as alignment marks in vertical cutting of the final
 1214   pages.
 1215   
 1216   @<Write vertical crop marks with width measure@>=
 1217   {
 1218      fprintf(OUTSTREAM,"\\hskip %1.3fpt\\vrule height20pt width%1.3fpt%%\n",
 1219         20.0-clthick/2.0,clthick);
 1220      fprintf(OUTSTREAM,"\\hbox to%1.3fpt{\\hfil",facewidth-clthick);
 1221      fprintf(OUTSTREAM,"$\\matrix{{%1.3f{\\rm\\ pt}/%1.3f{\\rm\\ mm}}"
 1222         "\\cr{}\\cr}$\\hfil}%%\n",facewidth,facewidth*(25.4/72.27));
 1223      fprintf(OUTSTREAM,"\\vrule height20pt width%1.3fpt%%\n",clthick);
 1224      fprintf(OUTSTREAM,"\\hbox to %1.3fpt{\\hfil",facewidth-clthick);
 1225      fprintf(OUTSTREAM,"$\\matrix{{%1.3f{\\rm\\ pt}/%1.3f{\\rm\\ mm}}"
 1226         "\\cr{}\\cr}$\\hfil}%%\n",facewidth,facewidth*(25.4/72.27));
 1227      fprintf(OUTSTREAM,"\\vrule height20pt width%1.3fpt\\par\\nointerlineskip\n",
 1228         clthick);
 1229   }
 1230   
 1231   @ The following block is analogous to the previous one, but now instead
 1232   considering horizontal crop marks, to be used as alignment marks in
 1233   horizontal cutting of the final pages.
 1234   
 1235   @<Write horizontal crop marks with height measure@>=
 1236   {
 1237      fprintf(OUTSTREAM,"\\vskip\\linethick\n");
 1238      fprintf(OUTSTREAM,"\\vrule height%1.3fpt width20pt",clthick);
 1239      fprintf(OUTSTREAM,"\\hskip %1.3fpt",2.0*facewidth);
 1240      fprintf(OUTSTREAM,"\\vrule height%1.3fpt width20pt\\par\\nointerlineskip\n",
 1241         clthick);
 1242      fprintf(OUTSTREAM,"\\vskip\\linethick\n");
 1243   }
 1244   
 1245   @ Generating the closing \TeX\ source code for the labels.
 1246   
 1247   @<Save closing source code@>=
 1248   {
 1249      if ((num_labels!=2)&&(num_labels!=4)) {
 1250         fprintf(OUTSTREAM,"\\par\\nointerlineskip\n");
 1251      }
 1252      if (num_labels!=num_labels_per_page) {
 1253         if (num_labels!=0) {
 1254            if (generate_crop_marks) {
 1255               @<Write horizontal crop marks with height measure@>@;
 1256               @<Write vertical crop marks with width measure@>@;
 1257            }
 1258         }
 1259         @<Close output page@>@;
 1260      }
 1261      fprintf(OUTSTREAM,"\\bye\n");
 1262      if (!outfile_specified)
 1263         fprintf(OUTSTREAM,"%%-------- TEX CODE ENDS HERE -----------------\n");
 1264   }
 1265   
 1266   @ Compiling the output \TeX\ source code. If the {\tt -c} or {\tt --compile}
 1267   option was present at the command line during startup of \dvlabel, then
 1268   the program will make use of \DVIPS\ to compile the previously generated
 1269   \TeX\ source code into PostScript.
 1270   If the {\tt -c} or {\tt --compile} option is used together with a specified
 1271   output file (specified using the {\tt-o} or {\tt --outputfile} options),
 1272   then this output file will be compiled.
 1273   On the other hand, if the {\tt -c} or {\tt --compile} option is used while
 1274   the program should send the generated source to |stdout|, then the internally
 1275   stored lines of output will be compiled instead (hence eliminating the need
 1276   for a temporary file for the compilation).
 1277   
 1278   @<Compile source code@>=
 1279   {
 1280      if (compile) {
 1281         if (verbose) {
 1282            fprintf(stdout,"%s: Compiling the TeX source code into PostScript.\n",
 1283               progname);
 1284         }
 1285         if (outfile_specified) {
 1286            if (eps_output) {
 1287               sprintf(tmpstr,"tex %s; dvips %s %s -E -o %s.eps",
 1288                  outputfilename,dvipsopts,outputfilename,outputfilename);
 1289            } else {
 1290               sprintf(tmpstr,"tex %s; dvips %s %s -o %s.ps",
 1291                  outputfilename,dvipsopts,outputfilename,outputfilename);
 1292            }
 1293            system(tmpstr); /* System call to execute |tmpstr| */
 1294         } else {
 1295            fprintf(stdout,"Compiling terminal output: Not implemented yet.\n");
 1296            exit(FAILURE);
 1297         }
 1298      }
 1299   }
 1300   
 1301   @*Index.
 1302   

Return to previous page

Generated by ::viewsrc::

Last modified Wednesday 15 Feb 2023