home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* */
- /* Description: Ascii to PostScript printer program. */
- /* File: imag:/users/local/a2ps/a2ps.c */
- /* Created: Mon Nov 28 15:22:15 1988 by miguel@imag (Miguel Santana) */
- /* Version: 2.0 */
- /* */
- /* Edit history: */
- /* 1) Derived of shell program written by evan@csli (Evan Kirshenbaum). */
- /* Written in C for improve speed execution and portability. Many */
- /* improvements have been added. */
- /* */
- /************************************************************************/
-
- /*
- * Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
- *
- * Permission is granted to copy and distribute this file in modified
- * or unmodified form, for noncommercial use, provided (a) this copyright
- * notice is preserved, (b) no attempt is made to restrict redistribution
- * of this file, and (c) this file is not distributed as part of any
- * collection whose redistribution is restricted by a compilation copyright.
- */
-
-
- #include <stdio.h>
- #ifdef ANSIC
- #include <time.h>
- #include <stdlib.h>
- #else
- #ifdef UNIX
- #include <sys/time.h>
- #else
- #ifdef SYSV
- #include <sys/types.h>
- #include <sys/timeb.h>
- #include <time.h>
- #else
- error !
- #endif
- #endif
- #endif
-
- #ifndef HEADER_PS
- #define HEADER_PS ".\\header.ps"
- #endif
- #define LINESPERPAGE 66
- #define COLUMNSPERLINE 86
-
- #define FALSE 0
- #define TRUE 1
-
- int fold_line();
- void print_file();
- char cut_line();
-
-
- int column = 0; /* Column number (in current line) */
- int line = 0; /* Line number (in current page) */
- int line_number = 0; /* Source line number */
- int first_page; /* First page for a file */
- int nonprinting_chars, chars; /* Number of nonprinting and total chars */
- int prefix_width; /* Width in characters for line prefix */
- int numbering = TRUE; /* Line numbering option */
- int folding = TRUE; /* Line folding option */
- int restart = TRUE; /* Restart page number at each file option */
- int only_printable = FALSE; /* Replace non printable char by space option */
- int interpret = TRUE; /* Interpret TAB, FF and BS chars option */
- int print_binaries = FALSE; /* Force printing for binary files */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int narg;
- char *arg;
-
- /* Option processing */
- arg = argv[narg = 1];
- while (narg < argc && arg[0] == '-')
- {
- switch (arg[1])
- {
- case 'b':
- if (arg[2] != NULL)
- goto usage;
- print_binaries = TRUE;
- break;
- case 'f':
- if (arg[2] != NULL)
- goto usage;
- folding = TRUE;
- break;
- case 'i':
- if (arg[2] != NULL)
- goto usage;
- interpret = TRUE;
- break;
- case 'n':
- if (arg[2] == NULL)
- {
- numbering = TRUE;
- break;
- }
- if (arg[3] != NULL)
- goto usage;
- switch (arg[2])
- {
- case 'b':
- print_binaries = FALSE;
- break;
- case 'f':
- folding = FALSE;
- break;
- case 'i':
- interpret = FALSE;
- break;
- case 'n':
- numbering = FALSE;
- break;
- case 'r':
- restart = FALSE;
- break;
- case 'v':
- only_printable = TRUE;
- break;
- default:
- goto usage;
- }
- break;
- case 'r':
- if (arg[2] != NULL)
- goto usage;
- restart = TRUE;
- break;
- case 'v':
- if (arg[2] != NULL)
- goto usage;
- only_printable = FALSE;
- break;
- default:
- usage:
- fprintf(stderr,
- "usage: a2ps [-n{bfinrv}] [-b] [-f] [-i] [-n] [-r] [-v] [f1 f2 ... fn]");
- exit(1);
- }
- arg = argv[++narg];
- }
- if (narg >= argc)
- goto usage;
-
- /* Header printing (postcript prolog) */
- print_header();
-
- /* Print files designated or standard input */
- prefix_width = numbering ? 6 : 1;
- if (narg >= argc)
- print_file("stdin");
- else
- {
- while (narg < argc)
- {
- if (freopen(arg, "r", stdin) == NULL)
- {
- fprintf(stderr, "Error opening %s\n", arg);
- printf("cleanup\n%c",4); /*^D is the reset command for PostScript*/
- exit(1);
- }
- print_file(arg);
- arg = argv[++narg];
- }
- }
-
- printf("cleanup\n%c",4); /*^D is the reset command for Postscript */
- }
-
- void print_file(name)
- char *name;
- {
- register int c;
- int start_line, continue_exit;
- int char_width;
-
- /*
- * Printing binary files is not very useful. We stop printing
- * if we detect one of these files. Our heuristic to detect them:
- * if 50% characters of first page are non-printing characters,
- * the file is a binary file.
- * Option -b force binary files impression.
- */
- first_page = TRUE;
- nonprinting_chars = chars = 0;
-
- /*
- * Preprocessing (before printing):
- * - TABs expansion (see interpret option)
- * - FF and BS interpretation
- * - replace non printable characters by a space or a char sequence
- * like:
- * ^X for ascii codes < 0x20 (X = [@, A, B, ...])
- * ^? for del char
- * M-c for ascii codes > 0x3f
- * - prefix parents and backslash ['(', ')', '\'] by backslash
- * (escape character in postcript)
- */
- column = 0;
- line = line_number = 0;
- start_line = TRUE;
-
- /* Leslie Spiro 21/10/89
- * Under DOS the file name will contain '\' chars as path seperators,
- * these need to be double in order to print correctly, so replace
- * the following line from the original
- printf("(%s) newfile\n", name);
- * with :
- */
- {
- char *pNextChar = name;
- char Next;
-
- printf("(");
- while (Next = *pNextChar++)
- {
- putchar( Next );
- if (Next=='\\')
- {
- putchar( Next );
- }
- } /*while*/
- printf(") newfile\n", name);
- }
-
-
- if (restart)
- printf("/sheet 1 def\n");
- printf("startpage\n");
-
- c = getchar();
- while (c != EOF)
- {
- /* Form feed */
- if (c == '\f' && interpret)
- {
- if (!start_line)
- printf(") s\n");
- start_line = TRUE;
- printf("endpage startpage\n");
- if (first_page && is_binaryfile(name))
- return;
- line = 0;
- if ((c = getchar()) == EOF)
- break;
- }
-
- /* Start a new line? */
- if (start_line)
- {
- if (numbering)
- printf("(%-5d ", ++line_number);
- else
- printf("( ");
- start_line = FALSE;
- }
-
- /* Interpret each character */
- switch (c)
- {
- case '\b':
- if (!interpret)
- goto print;
- if (column)
- column--;
- putchar(c);
- break;
- case '\n':
- column = 0;
- start_line = TRUE;
- printf(") s\n");
- if (++line >= LINESPERPAGE)
- {
- printf("endpage startpage\n");
- if (first_page && is_binaryfile(name))
- return;
- line = 0;
- }
- break;
- case '\t':
- if (interpret)
- {
- continue_exit = FALSE;
- do
- {
- if (++column + prefix_width > COLUMNSPERLINE)
- if (folding)
- {
- if (fold_line(name) == FALSE)
- return;
- }
- else
- {
- c = cut_line();
- continue_exit = TRUE;
- break;
- }
- putchar(' ');
- } while (column & 0x7);
- if (continue_exit)
- continue;
- break;
- }
- default:
- print:
- if (only_printable)
- char_width = 1;
- else
- {
- char_width = c > 0177 ? 2 : 0;
- char_width += c < ' ' || c == 0177 ? 2 : 1;
- }
- if (prefix_width + (column += char_width) > COLUMNSPERLINE)
- if (folding)
- {
- if (fold_line(name) == FALSE)
- return;
- }
- else
- {
- c = cut_line();
- continue;
- }
- if (c == '(' || c == ')' || c == '\\')
- putchar('\\');
- if (c >= ' ' && c < 0177)
- putchar(c);
- else
- {
- nonprinting_chars++;
- if (only_printable)
- putchar(' ');
- else
- {
- if (c > 0177)
- {
- printf("M-");
- c &= 0177;
- }
- if (c < ' ')
- printf("^%c", c+'@');
- else if (c == 0177)
- printf("^?");
- else
- putchar(c);
- }
- }
- chars++;
- break;
- }
- c = getchar();
- }
-
- if (!start_line)
- printf(") s\n");
- printf("endpage\n");
- }
-
- int fold_line(name)
- char *name;
- {
- column = 0;
- printf(") s\n");
- if (++line >= LINESPERPAGE)
- {
- printf("endpage startpage\n");
- if (first_page && is_binaryfile(name))
- return FALSE;
- line = 0;
- }
- if (numbering)
- printf("( ");
- else
- printf("( ");
-
- return TRUE;
- }
-
- char cut_line()
- {
- char c;
-
- while ((c = getchar()) != EOF && c != '\n' && c != '\f');
- return c;
- }
-
- is_binaryfile(name)
- char *name;
- {
- first_page = FALSE;
- /* There is a bug which causes a run time error if the first character
- * in a file is a line feed, I think this is because chars is 0.
- * So as a quick hack disable this check if chars==0 LS 27/11/89
- */
- if (!print_binaries && (chars!=0) && (nonprinting_chars*100/chars) >= 75)
- {
- fprintf(stderr, "%s is a binary file: printing aborted\n", name);
- return TRUE;
- }
- return FALSE;
- }
-
- print_header()
- {
- register int c;
- FILE *f;
- char *string;
- #ifdef ANSIC
- time_t date;
- #else
- #ifdef UNIX
- struct timeval date;
- struct tm *p;
- #else
- #ifdef SYSV
- struct timeb date;
- #endif
- #endif
- #endif
- char *pFileName=HEADER_PS;
-
- #ifdef ANSIC
- /* Get the file name of the post script header file from an environment
- * file, take it from the present directory if nothing defined
- */
- pFileName = getenv("HEADER_PS");
- if (!pFileName)
- pFileName=HEADER_PS;
- /*if*/
- #endif
-
- if ((f = fopen(pFileName, "r")) == NULL)
- {
- fprintf(stderr, "Poscript header (%s) missing\n", HEADER_PS);
- exit(1);
- }
-
- /* Header file printing */
- while ((c = getc(f)) != EOF)
- putchar(c);
-
- /* Retrieve date and hour */
- #ifdef ANSIC
- if (time(&date) == -1)
- {
- fprintf(stderr, "Error calculing time\n");
- exit(1);
- }
- string = ctime(&date);
-
- /* and print them */
- printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
- #else
- #ifdef UNIX
- (void) gettimeofday(&date, (struct timezone *)0);
- p = localtime(&date.tv_sec);
- string = asctime(p);
-
- /* and print them */
- printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
- #else
- #ifdef SYSV
- (void)ftime(&date);
- string = ctime(&date.time);
- printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
- #endif
- #endif
- #endif
-
- /* Go on */
- printf("startdoc\n");
- }