daps.c revision e5190c108bde19ca4d7c03b1d1eab7b00bd3a1ed
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1989 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
* The Regents of the University of California
* All Rights Reserved
*
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/****************************************************************************
* *
* This is the post-processor for the APS-5 phototypesetter. The *
* language that is accepted by this program is produced by the new device *
* independent troff, and consists of the following statements, *
* *
* *
* sn set the point size to n *
* fn set the typesetter font to the one in position n *
* cx output the ASCII character x *
* Cxyz output the code for the special character xyz. This *
* command is terminated by white space. *
* Hn go to absolute horizontal position n *
* Vn go to absolute vertical position n ( down is positive ) *
* hn go n units horizontally from current position *
* vn go n units vertically from current position *
* nnc move right nn units, then print the character c. This *
* command expects exactly two digits followed by the *
* character c. *
* w paddable word space - no action needed *
* nb a end of line ( information only - no action needed ) *
* pn begin page n *
* Dt ...\n draw operation 't': *
* *
* Dl x y line from here to x,y *
* Dc d circle of diameter d, left side here *
* De x y ellipse of axes x,y, left side here *
* Da u v x y arc *
* D~ x y x y wiggly line by x,y then x,y *
* *
* x ... \n device control functions: *
* *
* x i initialize the typesetter *
* x T s name of device is s *
* x r n h v resolution is n units per inch. h is *
* min horizontal motion, v is min vert. *
* motion in machine units. *
* x p pause - can restart the typesetter *
* x s stop - done forever *
* x t generate trailer - no-op for the APS *
* x f n s load font position n with tables for *
* font s. Referring to font n now means *
* font s. *
* x H n set character height to n *
* x S n set character slant to n *
* *
* Subcommands like i are often spelled out as "init" *
* *
* To get the post-processor running properly on your system, you may *
* have to make one or more of changes: *
* *
* Choose the appropriate description of your typesetter. These *
* values include the type of lens and the maximum master range *
* for your fonts. The values that you will need to adjust are *
* macros and defined constants located at the start of the *
* daps.h file. *
* *
* Make sure the variable 'typesetter' is properly initialized *
* to the APS-5 typesetter file on your system. If you are not *
* going to have daps directly drive the typesetter, you may *
* be stdout. (file daps.g) *
* *
* Make sure that the accounting file pathname 'tracct' is the *
* the accounting file that you want. If no accounting is to be *
* done then initialize it to the null string. (file daps.g) *
* *
* Check to make sure that 'fontdir' is the directory that *
* contains the devaps directory where your font tables are *
* located. (file daps.g) *
* *
* If there are no characters on your font disk that need any *
* adjustment in their vertical placement, then make sure that *
* the conditional compilation flag ADJUST is undefined. I would *
* recommend that you start this way to see what your font disk *
* really looks like. (file daps.h) *
* *
* *
****************************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include "aps.h" /* APS-5 opcode definitions */
#include "dev.h" /* font and dev structure declarations */
#include "daps.h" /* constant and macro definitions */
#include "daps.g" /* global variable definitions */
/*****************************************************************************/
int
{
/********************************************************************
* *
* This is the main program for the APS-5 post-processor. It *
* is responsible for calling the sequence of routines that are *
* needed to translate troff's new typesetter independent output *
* language into a form that will be understood by the APS-5 *
* phototypesetter. *
* *
********************************************************************/
out_file();
init_signals(); /* set up signal handling */
acct_file(); /* open the accounting file */
account(); /* make sure we charge this guy */
done(); /* finish up this job and reset the APS */
return (0);
} /* End of main */
/****************************************************************************/
int
{
int save; /* used to adjust arg_index */
int v_step; /* vertical step in -V option */
double atof(); /* used in getting beam cutoff postion */
int ch;
int i, sharpsign;
extern char *optarg;
extern int optind;
/********************************************************************
* *
* This is the routine that processes the command line option *
* list. The macro SET_ARGS uses the global variable arg_index to *
* properly initialize the local argc and argv values, while the *
* macro COUNT_ARGS adjusts the value of arg_index to account for *
* the number of arguments that were just processed. *
* *
* The options that are currently available in this driver *
* are, *
* *
* -f dir - use dir as the font directory *
* -F dir - same *
* *
* -t - use standard output *
* *
* -r - report the number of pages *
* *
* -A - do accounting even if there is no real *
* accounting file. If tracct is NULL then *
* the accounting information is written *
* to stderr. This is the way things are *
* done on our APS. *
* *
* -b - report whether typesetter is busy or *
* not. Nothing is printed. *
* *
* -w - wait until typesetter is available, *
* then procees the job. *
* *
* -o[str] - process only this list of pages. The *
* list may contain single pages or page *
* ranges, where the latter consists of *
* a pair of pages separated by -. *
* *
* -s[num] - stop processing every num pages, and *
* HALT the typesetter. *
* *
* -v[num] - use num as the maximum vertical step *
* size up or down the page. The argument *
* num is interpreted as 10ths of a point. *
* *
* -h[str] - use str as the string to be printed *
* in the header. *
* *
* -H[str] - use str as the pathname of the file *
* whose first line contains the string *
* to be printed in the header. *
* *
* -d[str] - toggle the debug flags for each number *
* contained in the string str. If str *
* contains the character '*' then all of *
* the debug flags will be toggled. *
* *
* -D[str] - dump all of the debug information into *
* file str. If this option is not used *
* then the debugging stuff is written to *
* stderr. *
* *
* -L[str] - use the file str as the log file for *
* all error messages. If this option is *
* not used then all error messages will *
* be written to stderr. *
* *
* -I - ignore all FATAL errors. This option is *
* only to be used for debugging - it may *
* cause a core file to be written. *
* *
********************************************************************/
!= EOF) { /*read options list*/
switch ( ch ) { /* check option */
case 'f': /* font directory */
case 'F':
break;
case 't': /* use standard output */
break;
case 'r': /* print page report */
break;
case 'A': /* do accounting! */
break;
case 'b': /* check if busy or not */
break;
case 'w': /* wait til APS is free */
break;
case 'o': /* process page list */
break;
case 's': /* stop every spage(s) */
if ( spage <= 0 ) /* illegal page number */
spage = 9999;
break;
case 'h': /* banner is in argument */
print_banner = YES;
break;
case 'H': /* banner is in file */
print_banner = YES;
break;
case 'd': /* selective debug */
break;
case 'D': /* set up debug file */
break;
case 'L': /* set up log file */
break;
case 'I': /* ignore fatal errors */
break;
case 'v': /* set max vertical step */
if ( v_step != 0 )
: -v_step;
break;
case 'c': /* set beam cutoff */
break;
case '#':
sharpsign = 1;
break;
default: /* didn't find it */
break;
} /* End of switch */
} /* End while */
if (sharpsign == 1) {
for (i=0; i<nolist; i+=2)
for (i=0; i<MAX_DEBUG; i+=4)
}
return (0);
} /* End of get_options */
/*****************************************************************************/
int
{
int save; /* used to adjust arg_index before exit */
/********************************************************************
* *
* This routine is called by main to handle the processing *
* of the input files from the command line. If there were no *
* files specified in the call then the post-processor will read *
* from the standard input. Otherwise it will process all of the *
* input files in the list, concatenating the output from each *
* one onto the output file. The only convention that is used for *
* input file names is that the character '-' as a file name will *
* cause the driver to read from the standard input, provided it *
* isn't the first 'file' in the list of input files. It would *
* probably be better if we chose some other character or sequence *
* of characters for this purpose. *
* *
********************************************************************/
else { /* read input file list */
while ( --argc > 0 ) { /* rest of the args are input files */
continue; /* in case we ignore this error */
} /* End else */
} /* End of while */
} /* End else */
return (0);
} /* End of process_input */
/****************************************************************************/
int
{
void wrap_up(); /* signal handling routine */
void float_err(); /* handles floating point errors */
/********************************************************************
* *
* This routine is called by main to set up the appropriate *
* handling of external signals for the post-processor. As *
* currently written interrupts, quits and hangups are all either *
* ignored or processed by the routine wrap_up(). *
* *
********************************************************************/
} else { /* wrap_up() handles them */
} /* End if */
return (0);
} /* End of init_signals */
/*****************************************************************************/
int
char *str; /* string of debug flags */
{
int index; /* single debug flag to toggle */
int i; /* for loop index */
/********************************************************************
* *
* This routine is called by main() when it finds the -d *
* option. The parameter str is a pointer to a string of comma *
* separated tokens from the command line that specify which of *
* the debug flags is to be toggled. As currently implemented the *
* tokens in str may consist of numbers, which specify the actual *
* flag to be toggled, or the character '*', which stands for all *
* of the available debug flags. *
* *
********************************************************************/
while ( *str ) {
for ( i = 0; i < MAX_DEBUG; i++ )
} /* End while */
return (0);
} /* End of debug_select */
/*****************************************************************************/
int
char *str; /* debug file pathname */
{
/********************************************************************
* *
* This routine is called by get_options() when it finds the *
* -D option in the command line. The parameter str is a pointer *
* to the pathname of the file to be used for all of the debugging *
* output. If the -D option is not specified then by default all *
* the debug output is written to stderr. *
* *
********************************************************************/
} /* End if */
return (0);
} /* End of debug_file */
/*****************************************************************************/
int
char *str; /* log file pathname */
{
/********************************************************************
* *
* This routine is called to open the log file for the APS-5 *
* post-processor. The pathname of the file is passed in the *
* parameter str when this routine is called from get_options(). *
* If the log file isn't specified then the post-processor will *
* write all of it's error messages to stderr. *
* *
********************************************************************/
} /* End if */
return (0);
} /* End of log_file */
/*****************************************************************************/
int
{
/********************************************************************
* *
* This routine is called to open the accounting file whose *
* pathname is pointed to by the variable tracct. If there is no *
* pathname in tracct then nothing is done in this routine, while *
* if we are unable to open the accounting file then an error *
* message is printed out and we quit. *
* *
********************************************************************/
if ( *tracct ) { /* we have an accnt file pathname */
} /* End if */
} /* End if */
return (0);
} /* End of acct_file */
/*****************************************************************************/
int
char *str; /* banner file pathname */
{
/********************************************************************
* *
* This routine is called from get_options() to read the *
* banner string from the first line of the file whose pathname is *
* contained in the string str. *
* *
********************************************************************/
return (0);
} /* End if */
return (0);
} /* End of ban_file */
/*****************************************************************************/
int
out_file()
{
/********************************************************************
* *
* This routine is called from the main program to open the *
* file pointed to by typesetter. *
* *
********************************************************************/
do {
exit(0);
} /* End if */
} /* End if */
} /* End if */
return (0);
} /* End of out_file */
/*****************************************************************************/
int
char *str; /* string of pages to process */
{
int i; /* loop index - debug only */
/********************************************************************
* *
* This routine is called when the -o option is read in *
* the command line. The parameter str points to a list of page *
* numbers to be processed. This list consists single pages or *
* page ranges, separated by commas. A page range is specified by *
* separating two page numbers by the character '-'. In this case *
* all pages in this closed interval will be processed by daps. *
* *
********************************************************************/
start = 0;
str++; /* so skip the minus sign */
} /* End if */
} /* End while */
if ( *str ) /* too many pages for olist array */
for ( i = 0; i < nolist; i += 2 )
return (0);
} /* End of outlist */
/*****************************************************************************/
int
int kind; /* kind of error ie. FATAL or NON_FATAL */
char *str; /* pointer to message to be printed */
{
void wrap_up(); /* signal handling routine */
/********************************************************************
* *
* This routine is called when the post-processor has found *
* an internal error. The parameter kind has the value FATAL or *
* NON_FATAL, and accordingly determines whether processing will *
* continue or not. The parameter str is a pointer to the error *
* message that is to be printed. All the remaining parameters *
* are the arguments that may be referenced in the control string *
* str. *
* *
* The global variable ignore is initialized to NO in the *
* file daps.globals, and can be set to YES by using the -I option *
* in the command line. This will allow the post-processor to *
* continue after a normally FATAL error has been encountered. *
* This is only a debugging feature and should not generally be *
* used. *
* *
********************************************************************/
if ( line_number > 0 )
return (0);
wrap_up(); /* so quit */
return (0);
} /* End of error */
/*****************************************************************************/
int
done()
{
/********************************************************************
* *
* This routine is called to do the final processing for the *
* current job. If there is to be any accounting for this job we *
* need to be sure that the account function is called first *
* because there is nothing more we can do when we get here. *
* *
********************************************************************/
return (0);
} /* End of done */
/*****************************************************************************/
int sig; /* signal number - not used */
{
/********************************************************************
* *
* Called when a floating point error has been detected. *
* Needed because we want to make sure we exit gracefully if a *
* users job would normally dump a core file. *
* *
********************************************************************/
} /* End of float_err */
/*****************************************************************************/
int sig; /* signal number - not used */
{
/********************************************************************
* *
* This routine is called to make sure that all the necessary *
* stuff is done when the driver finishes its job because of some *
* external signal or because it encountered a FATAL syntax error. *
* *
********************************************************************/
account(); /* keep some kind of record for this job */
done(); /* get the APS ready for next job */
} /* End of wrap_up */
/*****************************************************************************/
int
{
int ch; /* first character of the command */
int c; /* used only as a character */
int n; /* general purpose integer variable */
/********************************************************************
* *
* This is the main interpreter for the post-processor. It is *
* called from routine process_input with the single parameter *
* fp, which is the file descriptor for the current input file. *
* *
* The global variable line_number is used to keep track of *
* the current line in the input file fp. Its value is adjusted *
* in both conv() and devcntrl() and it is used in the routine *
* error() when error messages are written to the file fp_error. *
* *
* The bits in the global variable x_stat are used to keep *
* track of the progress of the post-processor, and when the *
* program exits it will return x_stat as its termination status. *
* *
* *
* NOTE - In order to improve the speed of this routine we may *
* want to declare more register variables. When we do this we *
* need to be sure that the macros that are being used will accept *
* register variables as arguments. For example if a macro takes *
* the address of one of its arguments, then we can't assign this *
* variable to a register. *
* *
********************************************************************/
switch ( ch ) { /* ch determines the command */
case 'w': /* don't do anything for these */
case ' ':
case 0:
break;
case '\n': /* just increment line_number */
line_number++;
break;
case '0': /* two motion digits and a char */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
/* Be careful - we need to fall through here */
case 'c': /* single ASCII character */
put1(c); /* output c's APS-5 code */
break;
case 'h': /* relative horizontal motion */
case 'H': /* absolute horizontal motion */
case 'v': /* relative vertical motion */
case 'V': /* absolute vertical motion */
case 's': /* set point size */
case 'p': /* start a new page */
switch( ch ) { /* and then process the command */
case 'h': hmot(n);
break;
case 'H': hgoto(n);
break;
case 'v': vmot(n);
break;
case 'V': vgoto(n);
break;
break;
case 'p': t_page(n);
break;
} /* End switch */
break;
case 'C': /* process special char string */
case 'f': /* set font */
if ( ch == 'C' )
break;
case 'x': /* device control function */
break;
case 'D': /* drawing operation */
case 't': /* text string upto newline */
if ( ch == 'D' )
line_number++; /* finished with this line */
break;
case 'n': /* end of line */
case '#': /* comment */
if ( ch == 'n' )
t_newline();
line_number++;
break;
default: /* illegal command - quit */
break; /* in case we ignore this error */
} /* End switch */
} /* End while */
return (0);
} /* End of conv */
/*****************************************************************************/
int
char buf[]; /* drawing command */
{
/********************************************************************
* *
* This routine interprets the drawing functions that are *
* provided by troff. The array buf[] has been filled in by the *
* function conv(), and it contains the drawing command line from *
* the input file. *
* *
********************************************************************/
switch ( buf[0] ) { /* process the command */
case 'l': /* draw a line */
break;
case 'c': /* draw a circle */
break;
case 'e': /* draw an ellipse */
break;
case 'a': /* draw an arc */
break;
case '~': /* draw spline curve */
break;
#ifdef PLOT
case 'p': /* plot these points */
break;
#endif
default: /* don't understand the command */
break; /* in case we ignore this error */
} /* End switch */
return (0);
} /* End of drawfunct */
/*****************************************************************************/
int
{
int c; /* character used in SKIP_LINE */
int n; /* integer used in GET_INT */
/********************************************************************
* *
* This is the interpreter for the device control language *
* that is produced by the new troff. The parameter fp is the file *
* descriptor for the current input file. *
* *
********************************************************************/
switch ( str[0] ) { /* str[0] determines the command */
case 'i': /* initialize the device */
fileinit(); /* read data from DESC.out */
t_init(); /* initialize the typesetter */
t_banner();
break;
case 'T': /* set device name */
break;
case 't': /* trailer - do nothing on APS-5 */
break;
case 'p': /* pause - we can restart */
case 's': /* stop - done with this job */
break;
case 'r': /* set resolution */
break;
case 'f': /* load a font */
file[0] = 0; /* in case there is no file name */
break;
case 'H': /* set character height */
break;
case 'S': /* set character slant */
t_slant(n); /* set the APS slant to n */
last_req_slant = n; /* and remember this angle */
break;
default: /* don't understand the command */
break; /* in case we ignore this error */
} /* End switch */
line_number++;
return (0);
} /* End of devcntrl */
/*****************************************************************************/
int
t_init()
{
int i; /* for loop variable */
/********************************************************************
* *
* This routine is called from devcntrl() when the command *
* x init is read. It produces the instructions that initialize *
* the APS, and then it sets up the picture drawing variables *
* drawdot and drawsize. *
* *
* *
* NOTE - the opcode STRTJOB is defined to be octal 272 in the *
* file aps.h, although on our APS-5 typesetter it is one of the *
* reserved but not implemented opcodes. *
* *
********************************************************************/
putint(0);
for ( i = 0; i < nchtab; i++ ) /* find drawing character index */
break;
if ( i < nchtab ) { /* found it in the table */
drawsize = 1;
} else { /* didn't find it - use default */
drawdot = '.';
drawsize = 3;
} /* End if */
return (0);
} /* End of t_init */
/*****************************************************************************/
int
t_banner()
{
int i; /* while loop counter */
char *bp; /* temp pointer to banner string */
/********************************************************************
* *
* This routine is called from devcntrl() when the device *
* initialization command is read. It is responsible for printing *
* the job's header. This includes checking and then writing out *
* the string pointed to by banner. The user may set this string *
* by using either the -h or the -H options on the command line. *
* *
********************************************************************/
i = 0; /* characters looked at so far */
while ( *bp ) /* check at most BAN_LENGTH chars */
return (0);
} /* End of t_banner */
/*****************************************************************************/
int
t_page(n)
{
int i; /* for loop index */
/********************************************************************
* *
* This routine is called from conv() to do the work that is *
* necessary when we begin a new page. The STRTPG command to the *
* APS-5 invokes the RESET command which sets the font to 0000, *
* the master range to 1, and sets the oblique mode to normal and *
* the oblique angle to 14 degrees. To reset the font and range *
* properly we call setsize(), while if we were in oblique mode *
* the variable aps_slant will be non-zero and so in this case *
* we call routine t_slant() with aps_slant as the parameter. *
* *
********************************************************************/
scount = 0; /* and start counting over again */
} /* End if */
vpos = 0; /* we are at the top of new page */
putint(n);
++pageno; /* update user's page number */
if ( aps_slant ) /* then the APS was in oblique mode */
if ( nolist == 0 ) return (0); /* no -o option, so print every page */
break;
} /* End if */
return (0);
} /* End of t_page */
/*****************************************************************************/
int
{
/********************************************************************
* *
* This routine is called from conv() when it has read the *
* start new line command. This command has the form "n a b" where *
* a and b are integers that we can safely ignore for the APS-5. *
* *
********************************************************************/
hpos = 0; /* return to left margin */
return (0);
} /* End of t_newline */
/*****************************************************************************/
int
t_size(n)
int n; /* convert this point size */
{
int i; /* for loop index */
/********************************************************************
* *
* This routine is called to convert the point size n to an *
* internal size, which is defined as one plus the index of the *
* least upper bound for n in the array pstab[]. If n is larger *
* than all the entries in pstab[] then nsizes is returned. *
* *
* *
* NOTE - this routine expects the entries in pstab[] to be in *
* increasing numerical order, but it doesn't require this list to *
* be terminated by a 0 point size entry. *
* *
********************************************************************/
return(nsizes); /* so use largest internal size */
for ( i = 0; n > pstab[i]; i++ ) /* otherwise find the LUB for n */
;
return(i+1); /* internal size is i+1 */
} /* End of t_size */
/*****************************************************************************/
int
t_charht(n)
int n; /* set height to this internal size */
{
int max; /* max internal size for current range */
/********************************************************************
* *
* This routine is called by devcntrl() to set the height of *
* the characters that are being printed to the internal size *
* specified by the parameter n. If the requested size is too *
* large for the current range then an error message is written *
* and the requested size is set to the maximum allowed in the *
* current range. Since the APS-5 apparently allows us to decrease *
* the height as far as we want, no lower limit checks are made on *
* the requested size. The global variable range is set by the *
* routine setfont() to the current master range that is being *
* used. *
* *
********************************************************************/
return (0); /* in case this error is ignored */
} /* End if */
if ( n > max ) { /* requested size is too big */
n = max; /* reset n to largest allowed size */
} /* End if */
return (0);
} /* End of t_charht */
/*****************************************************************************/
int
upper_limit(n)
int n; /* find upper limit for this range */
{
int bsize; /* master range base size */
int max; /* maximum point size for range n */
int max_internal; /* maximum internal size for range n */
/********************************************************************
* *
* This routine is called by t_charht() and possibly others to *
* find the maximum internal size that is allowed for master range *
* n. The value returned to the caller is the largest internal *
* size that is allowed in this range. *
* *
********************************************************************/
if ( n <= 3 ) /* can scale these ranges up */
max_internal--;
return(max_internal);
} /* End of upper_limit */
/*****************************************************************************/
int
t_slant(n)
int n; /* set the APS slant to this value */
{
/********************************************************************
* *
* Called to set the slant angle to the value of the parameter *
* n. On the APS-5 we can only set positive or negative 14 degree *
* slants, even though in TROFF any slant angle can be requested. *
* The global variable last_slant is the value of the last angle *
* that was stored in the APS-5 using either the SETOBLIQUE or *
* STRTPG commands, while aps_slant is the last angle we set in *
* this routine. *
* *
* Originally we only set the oblique angle if last_slant *
* was not equal to n. This really didn't work too well, because *
* appaerntly the APS-5 resets the oblique angle to +14 degrees *
* when it returns to normal mode. *
* *
********************************************************************/
if ( n != 0 ) { /* need to slant type being set */
n = ( n > 0 ) ? POS_SLANT /* use +14 degree slant */
: NEG_SLANT; /* otherwise slant at -14 degrees */
last_slant = n; /* remember this stored angle */
} /* End if */
aps_slant = n; /* angle that type is being set at */
return (0);
} /* End of t_slant */
/*****************************************************************************/
int
char *str; /* convert this string to font number */
{
int n; /* integer value for number in str */
/********************************************************************
* *
* This routine is called from conv() to convert the ASCII *
* string *str to an integer that represents a legal font number. *
* If the resulting number is outside the allowed range for fonts *
* on this typesetter then an error message is printed out and *
* the program is aborted. *
* *
********************************************************************/
if ( n < 0 || n > nfonts ) { /* illegal font - abort */
n = font; /* in case we don't quit on an error */
} /* End if */
return(n); /* legal value so return it */
} /* End of t_font */
/*****************************************************************************/
int
char *str; /* typeset this string of characters */
{
int ch; /* internal character variable */
/********************************************************************
* *
* This routine is called by conv() to process the text string *
* that is in the array str. Characters are read from str and *
* written to the output file until the end of the string is *
* reached. *
* *
* After the character has been put in the output file the *
* current horizontal position is adjusted by a call to hmot() *
* using the global variable lastw as the parameter. lastw is set *
* in put1() and represents the width of the last character that *
* was printed. *
* *
********************************************************************/
if ( debug[2] )
case '(': /* special troff character sequence */
break;
case '\\': /* backslash character */
case 'e':
put1('\\');
break;
default: /* illegal character sequence */
break;
} /* End switch */
if ( debug[3] )
} /* End while */
return (0);
} /* End of t_text */
/*****************************************************************************/
int
int ch; /* pause or stop */
{
int n; /* for loop variable */
long dist; /* distance to end of job */
int opcode; /* ENDJOB or HALT */
/********************************************************************
* *
* This routine is called to produce the typesetter commands *
* that are required at the end of a job. If the parameter ch has *
* the value 's' then we have reached the end of the current job *
* and so we output the ENDJOB opcode, otherwise ch should be *
* equal to 'p', and so we produce the HALT command. This enables *
* the operator to restart the current job by pressing the PROCEED *
* button on the front panel, while if he hits the INITIAL button *
* the current job will be terminated. *
* *
* If we have finished this job, but we are not currently at *
* position max_vpos, we step the job forward to this position so *
* that the next job begins on unexposed paper. *
* *
********************************************************************/
while ( dist > 0 ) { /* go to the end of the job */
} /* End while */
} /* End if */
for ( n = 0; n < 10; n++ ) /* flush out APS internal buffer */
: ENDJOB; /* done with this guy */
return (0);
} /* End of t_reset */
/*****************************************************************************/
int
hflush()
{
/********************************************************************
* *
* This routine is called in put1() and t_push() to make sure *
* that the two variables hpos and htrue aren't too different. If *
* they differ by more than the constant SLOP then a tab is set *
* and then executed to position the beam properly. *
* *
* The variable hpos is the current horizontal position as *
* determined by troff, while htrue is the horizontal position as *
* calculated by the post-processor. *
* *
********************************************************************/
} /* End if */
return (0);
} /* End of hflush */
/*****************************************************************************/
int
hmot(n)
int n; /* move this far from here */
{
/********************************************************************
* *
* This routine is called from conv() to handle a relative *
* horizontal motion of n units. If n is positive then we move to *
* the right on the current line. If the final horizontal position *
* hpos is negative then something has gone wrong and so we print *
* out an error message and if we return from error() we set hpos *
* to 0. *
* *
********************************************************************/
hpos = 0; /* in case we ignore this error */
} /* End if */
return (0);
} /* End of hmot */
/*****************************************************************************/
int
hgoto(n)
int n; /* move to this horizontal position */
{
/********************************************************************
* *
* This routine is called by conv() to set the absolute *
* horizontal position of the beam to the position n, where n *
* must be a positive integer. *
* *
********************************************************************/
hpos = 0; /* in case we ignore this error */
} /* End if */
return (0);
} /* End of hgoto */
/*****************************************************************************/
int
vgoto(n)
int n; /* final absolute vert position */
{
/********************************************************************
* *
* This routine is called from conv() to position the beam at *
* the absolute vertical position n. The unit used in all of the *
* APS absolute spacing commands is 1/10 of a point. *
* *
* *
* NOTE - it is important to check that a job doesn't try to *
* write on a previous job by using the vertical spacing commands. *
* Currently this check is made in the routine vmot(). *
* *
********************************************************************/
return (0);
} /* End of vgoto */
/*****************************************************************************/
int
vmot(n)
int n; /* move n units vertically from here */
{
int i; /* for loop variable */
int sign; /* sign of the requested motion */
int dist; /* distance left to move */
/********************************************************************
* *
* This routine is called to move the vertical position of the *
* beam n units from the current position. The global variable *
* cur_vpos is the typesetter's current vertical position as *
* measured from the start of the job. If the user has requested *
* a relative vertical motion that would make cur_vpos negative *
* we print an error message and then abort. The variable max_vpos *
* is the maximum vertical position that this job has reached. It *
* is used to calculate the amount of paper that has been used. *
* *
********************************************************************/
if ( cur_vpos + n < 0 ) { /* trying to write on last job! */
return (0); /* in case we ignore this error */
} /* End if */
while ( dist > 0 ) { /* not done yet */
} /* End while */
vpos += n; /* record our new vertical position */
cur_vpos += n;
return (0);
} /* End of vmot */
/*****************************************************************************/
int
put1s(s)
char *s; /* print this special character */
{
int i; /* for loop index */
/********************************************************************
* *
* This routine is called to produce the typesetter output *
* for the special character string pointed to by s. All of the *
* special characters are listed in the charset portion of the *
* typsetter's DESC file, and the program makedev reads this part *
* of the DESC file and produces two tables called chtab[] and *
* chname[]. The character array chname[] contains the special *
* character strings separated by '\0', while chtab[i] gives us *
* the starting position in chname[] for the special character i. *
* *
* *
* NOTE - Since we just do a sequential search of the strings *
* in chname[] when looking for a special character, the speed of *
* the post-processor could be improved if we had the most common *
* special characters at the start of the list in the DESC file. *
* However before doing this we should find out how troff does *
* the lookup. *
* *
********************************************************************/
for ( i = 0; i < nchtab; i++ ) /* lookup the special character */
break;
if ( i < nchtab ) { /* found it */
#ifdef ADJUST
t_adjust(s); /* adjust vertical positions */
#endif
} /* End if */
else /* didn't find it - abort */
if ( debug[4] ) {
} /* End if */
return (0);
} /* End of put1s */
/*****************************************************************************/
#ifdef ADJUST
int
t_adjust(s)
char *s; /* look for this string */
{
int i; /* for loop index */
int incr; /* incrment v_adjust by this much */
/********************************************************************
* *
* Called from put1s() to look for the string *s in adj_tbl[] *
* and if found it is used to set the appropriate vertical for the *
* character. *
* *
********************************************************************/
v_adjust = 0;
for ( i = 0; adj_tbl[i] != '\0'; i++ )
break;
} /* End if */
return (0);
} /* End of t_adjust */
#endif
/*****************************************************************************/
int
put1(c)
int c; /* print this character */
{
int i; /* c's index in font data structures */
int k; /* look for c on this font */
int j; /* lookup failed on this many fonts */
int k1; /* if not found check this font next */
int code; /* APS-5 code for this character */
int old_font; /* original font number (1..nfonts) */
int old_range; /* original master range setting */
int last_range; /* last master range setting */
int old_slant; /* original device slant angle */
/********************************************************************
* *
* This routine is responsible for producing the output codes *
* for the characters to be printed by the APS. The integer c *
* is the ASCII code for the character if c < 128. Otherwise it *
* refers to one of troff's special character sequences. Since we *
* are not concerned with unprintable ASCII characters we subtract *
* 32 from c to get the right index to use when we do the lookup *
* in array fitab[][]. If the character isn't found on the current *
* font then we search all the remaining fonts, starting with the *
* first special font. If we haven't found the character after we *
* search the last font then an error message is written out and *
* we quit. Since we can't be guarenteed that font position 0 has *
* been loaded with a valid font, we need to make sure that the *
* circular search skips this position. *
* *
* If we find the character c, but it has an APS code that is *
* larger than 128, then the makedev program has encoded some *
* extra information in this field. Therefore we call the routine *
* special_case() to decode this info, and return the correct APS *
* code for c. *
* *
********************************************************************/
k = font; /* while loop looks for c on font k */
j = 0; /* c not found on this many fonts */
c -= 32; /* tables don't include unprintable chars */
if ( c <= 0 ) { /* c is a space or unprintable */
if ( c < 0 ) /* can't be in any of our font tables */
return (0); /* lastw = space width (see t_text()) */
} /* End if */
/* Look for character c in current font and then on the special fonts */
j++;
} /* End while */
/* If j > nfonts or i == 0 then char c not found. no-op if code = 0 */
if ( i == 0 || j > nfonts )
return (0);
} /* End if */
CHANGE_FONT(k, last_range);
} /* End if */
#ifdef ADJUST
if ( v_adjust != 0 )
#endif
hflush(); /* get to right horizontal position */
#ifdef ADJUST
if ( v_adjust != 0 ) {
v_adjust = 0;
} /* End if */
#endif
return (0);
} /* End of put1 */
/*****************************************************************************/
int
putint(n)
int n; /* write out this integer */
{
/********************************************************************
* *
* This routine is called to write the integer n out in the *
* last two bytes of a type two command on the APS-5 typesetter. *
* *
********************************************************************/
return (0);
} /* End of putint */
/*****************************************************************************/
int
setsize(n)
int n; /* new internal size */
{
/********************************************************************
* *
* This routine is called to set the current internal size to *
* the value n, and then output the commands needed to change the *
* APS-5 point size. The internal size n is an index into the *
* array pstab[], which contains the actual point size that is to *
* be used. *
* *
* *
* NOTE - This routine always calls setfont in case the range *
* has changed, but it may be the case that the range doesn't *
* really change even though the point size has changed. Always *
* making this call definitely produces some unnecessary APS-5 *
* code. Probably fix it in setfont routine. *
* *
********************************************************************/
if ( n <= 0 || n > nsizes ) { /* internal size out of range */
n = size; /* in case we return from this error */
} /* End if */
size = n; /* must preceed call to setfont() */
return (0);
} /* End of setsize */
/*****************************************************************************/
int
setfont(n)
int n; /* new font's internal number */
{
int oldrange; /* current master range */
/********************************************************************
* *
* This routine is called to set the current typesetter font *
* to the one that corresponds to the parameter n. These internal *
* font numbers are determined by the way the font tables are set *
* up for the typesetter in the DESC file. *
* *
* Our APS-5 typesetter typically has only master ranges 1, 2, *
* and 3. The actual font that we want to set is determined by the *
* current value of the global variable size. Remember that this *
* value is an internal size, which is an index into the array *
* pstab[]. The following table gives the point sizes that can be *
* used in the different master ranges, *
* *
* *
* MASTER RANGE 1: 0 to 12 *
* MASTER RANGE 2: 12 to 24 *
* MASTER RANGE 3: 24 to 48 *
* MASTER RANGE 4: 48 to 96 *
* *
* *
* although any range can actually print characters up to size, *
* *
* *
* 1.5 * limit - 1 *
* *
* *
* where the value of limit is obtained from the above table. *
* *
********************************************************************/
if ( n < 0 || n > nfonts ) {
n = font; /* in case we ignore this error */
} /* End if */
font = n; /* current internal font number */
return (0);
} /* End of setfont */
/*****************************************************************************/
int
change_font(n)
int n; /* new font's internal number */
{
int angle; /* slant angle - used in SETSLANT */
int max_range; /* largest range allowed on font n */
int max_size; /* largest size allowed in max_range */
char f_spare1; /* value of font flags */
/********************************************************************
* *
* This routine is called to change the font that the APS is *
* currently setting type in. Some extra stuff is done if the font *
* has any of its special flags set. *
* *
********************************************************************/
} /* End if */
} /* End if */
return (0);
} /* End of change_font */
/*****************************************************************************/
int
int n; /* update this font position */
char *s; /* font's external name (eg. R) */
char *si; /* font number used by the APS */
{
/********************************************************************
* *
* This routine is called to update the data structures that *
* are maintained by the post-processor to keep track of fonts. *
* The parameter n is the font position that we are going to *
* update, while s and si are the font's external and internal *
* names. *
* *
********************************************************************/
return (0);
} /* End of t_fp */
/*****************************************************************************/
int
account()
{
float pages; /* will charge for this many pages */
/********************************************************************
* *
* This is the accounting routine for the post-processor. It *
* may have to be changed for your particular system. *
* *
* NOTE - since the variable res can be changed we better use *
* the constant RES to determine how many pages were printed. *
* *
********************************************************************/
} /* End if */
return (0);
} /* End of account */
/*****************************************************************************/
int
int index; /* char position in tables */
int font; /* char info is on this font */
{
int old_range; /* saved value of current range */
int old_font; /* present APS-5 font number */
int req_font; /* requested APS-5 font number */
int max_range; /* max allowed range for character */
int max_size; /* max size allowed for max_range */
int angle; /* special char angle to set */
int code; /* old code - with bits set */
/********************************************************************
* *
* This routine is called by put1() to handle the special any *
* special case characters for the APS-5. *
* *
* Taken on its own, this is a very confusing routine, but one *
* which I found from my experience with the APS-5 at Murray Hill *
* was definitely needed. I'll try to give a brief, but hopefully *
* complete explination here. *
* *
* The additions that I made here needed to be completely *
* transparent to troff, and so the only field in the font tables *
* that could be changed was the actual charater code, since troff *
* can't possibly need this stuff (it's device independent!). On *
* the APS-5, character codes lie between 1 and 128 (inclusive) - *
* anything else is an actual function code. Therefore when we are *
* ready to print a character in put1(), and we find that its code *
* is larger than 128 we know something more has to be done. This *
* routine is then called to try to make sense out of the code, *
* do any of the special stuff required for this character, and *
* finially return its real code. This extra stuff can include *
* changing the character's slant, ensuring that the current *
* master range is not larger than a given value (max_range), and *
* finially getting the actual character from a completely *
* different font (alternate_font). What we actually do for each *
* special character is determined by its code in the current *
* set of font tables. This code is produced by a special version *
* of the makedev program, which I changed to interpret some *
* extra fields in the ASCII font tables. *
* *
* *
* NOTE - This extra stuff is costly, and should only be used *
* when absolutely necessary. The alternate font stuff can *
* cause many extra font changes, which in turn will force extra *
* disk accesses. We found this to be one of the main reasons for *
* slow jobs on our APS, not to mention the extra wear on the disk *
* drive. *
* *
********************************************************************/
} /* End if */
} /* End if */
} /* End if */
} /* End if */
} /* End of special_case */
/*****************************************************************************/
int
get_range(n)
int n; /* find the range for this point size */
{
int val; /* return this as the range */
int msize; /* size for master range val */
/********************************************************************
* *
* This routine is called to return the range corresponding to *
* the point size n. Note that n is not an internal size for this *
* routine. *
* *
********************************************************************/
val = 0;
} /* End while */
return(1); /* in case we ignore this error */
} /* End of get_range */
/*****************************************************************************/
int
fileinit()
{
int fin; /* input file descriptor */
int nw; /* number of font table entries */
int i; /* for loop index */
char *malloc(); /* memory allocation routine */
char *filebase; /* pointer to memory block */
char *p; /* pointer used to set up tables */
/********************************************************************
* *
* This routine is responsible for reading the DESC.out file *
* for the APS-5 typesetter, and then initializing the appropriate *
* data structures for the device and all of the default fonts *
* that were mentioned in the typesetter description file DESC. *
* *
* First the DESC.out file is opened and the structure dev is *
* initialized from the first part of the file. This structure *
* then contains all the information needed to enable us to finish *
* the initialization process. Next the rest of the file is read *
* in and the device tables pstab[], chtab[], and chname[] are set *
* up. After this has been done we enter a loop which handles the *
* initialization for all of the fonts that were mentioned in the *
* DESC file. Finially we allocate enough memory so that font *
* position 0 can be loaded with the tables from any valid font *
* in the library. *
* *
* *
* NOTE - the program 'makedev' creates all of the '.out' *
* files in the troff font library. This routine quite obviously *
* depends on how 'makedev' has written these files. In addition *
* the troff program also reads the '.out' files and it too *
* expects the same format as we do here! To really understand *
* this routine you need to look at 'makedev.c' and the ASCII *
* tables in the troff font library. *
* *
********************************************************************/
smnt = i; /* this is first special font */
p += sizeof(struct Font); /* font structure was written first */
widthtab[i] = p; /* next is this font's width table */
} /* End for */
if ( smnt == 0 ) /* no special fonts specified */
return (0);
} /* End of fileinit */
/*****************************************************************************/
int
fontprint(i)
int i; /* index of font to print out */
{
int j; /* for loop variable */
int n; /* number of width entries */
int pos; /* position of char from fitab array */
int count; /* count of characters in this font */
/********************************************************************
* *
* This is a debugging routine that is used to dump all of the *
* information about font i that was loaded from the '.out' file. *
* It is called from fileinit() when the debug flag 5 is turned *
* on, and from loadfont when flag 6 is set. *
* *
********************************************************************/
count = 0;
count++;
if ( j >= 96 ) /* special chars start at 128-32 */
} /* End if */
} /* End for */
return (0);
} /* End of fontprint */
/*****************************************************************************/
int
int num; /* font position to load */
char *name; /* name of the font to load */
char *fdir; /* name of directory to load from? */
{
int fin; /* font file descriptor */
int nw; /* width entries in new font file */
int norig; /* width entries in old font file */
/********************************************************************
* *
* This routine is called to load the font position num with *
* the data for the font name. If the string fdir is not null then *
* it is taken as the pathname of the directory that contains the *
* '.out' file for the font that we are to load, otherwise we load *
* this data from the standard font library. *
* *
********************************************************************/
return (0);
return (0);
} /* End of loadfont */
/*****************************************************************************/
int
int font; /* load '.add' tables for this font */
{
int nw; /* number of width entries for font */
int fin; /* font file descriptor */
/********************************************************************
* *
* This routine is called to read in the '.add' file for the *
* font that is loaded in the position specified by the parameter *
* font. These '.add' files are created by the special version of *
* the makedev program, which reads and interprets several extra *
* fields in the APS font tables. Included in the '.add' files are *
* the alternate font table and the APS-5 character code table. *
* *
********************************************************************/
return (0);
} /* End of load_alt */
/*****************************************************************************/