home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 19 Printer / 19-Printer.zip / PS_LIST.ZIP / A2PS.C next >
Text File  |  1989-11-27  |  11KB  |  480 lines

  1. /************************************************************************/
  2. /*                                    */
  3. /* Description: Ascii to PostScript printer program.            */
  4. /* File: imag:/users/local/a2ps/a2ps.c                    */
  5. /* Created: Mon Nov 28 15:22:15 1988 by miguel@imag (Miguel Santana)    */
  6. /* Version: 2.0                                */
  7. /*                                    */
  8. /* Edit history:                            */
  9. /* 1) Derived of shell program written by evan@csli (Evan Kirshenbaum).    */
  10. /*    Written in C for improve speed execution and portability. Many    */
  11. /*    improvements have been added.                    */
  12. /*                                    */
  13. /************************************************************************/
  14.  
  15. /*
  16.  * Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
  17.  *
  18.  * Permission is granted to copy and distribute this file in modified
  19.  * or unmodified form, for noncommercial use, provided (a) this copyright
  20.  * notice is preserved, (b) no attempt is made to restrict redistribution
  21.  * of this file, and (c) this file is not distributed as part of any
  22.  * collection whose redistribution is restricted by a compilation copyright.
  23. */
  24.  
  25.  
  26. #include <stdio.h>
  27. #ifdef ANSIC
  28. #include <time.h>
  29. #include <stdlib.h>
  30. #else
  31. #ifdef UNIX
  32. #include <sys/time.h>
  33. #else
  34. #ifdef SYSV
  35. #include <sys/types.h>
  36. #include <sys/timeb.h>
  37. #include <time.h>
  38. #else
  39. error !
  40. #endif
  41. #endif
  42. #endif
  43.  
  44. #ifndef    HEADER_PS
  45. #define    HEADER_PS    ".\\header.ps"
  46. #endif
  47. #define    LINESPERPAGE    66
  48. #define    COLUMNSPERLINE    86
  49.  
  50. #define    FALSE        0
  51. #define    TRUE        1
  52.  
  53. int fold_line();
  54. void print_file();
  55. char cut_line();
  56.  
  57.  
  58. int column = 0;            /* Column number (in current line) */
  59. int line = 0;            /* Line number (in current page) */
  60. int line_number = 0;        /* Source line number */
  61. int first_page;            /* First page for a file */
  62. int nonprinting_chars, chars;    /* Number of nonprinting and total chars */
  63. int prefix_width;        /* Width in characters for line prefix */
  64. int numbering = TRUE;        /* Line numbering option */
  65. int folding = TRUE;        /* Line folding option */
  66. int restart = TRUE;        /* Restart page number at each file option */
  67. int only_printable = FALSE;    /* Replace non printable char by space option */
  68. int interpret = TRUE;        /* Interpret TAB, FF and BS chars option */
  69. int print_binaries = FALSE;    /* Force printing for binary files */ 
  70.  
  71. main(argc, argv)
  72. int argc;
  73. char *argv[];
  74. {
  75.    int narg;
  76.    char *arg;
  77.  
  78.    /* Option processing */
  79.    arg = argv[narg = 1];
  80.    while (narg < argc && arg[0] == '-')
  81.    {
  82.       switch (arg[1])
  83.       {
  84.       case 'b':
  85.      if (arg[2] != NULL)
  86.         goto usage;
  87.      print_binaries = TRUE;
  88.      break;
  89.       case 'f':
  90.      if (arg[2] != NULL)
  91.         goto usage;
  92.      folding = TRUE;
  93.      break;
  94.       case 'i':
  95.      if (arg[2] != NULL)
  96.         goto usage;
  97.      interpret = TRUE;
  98.      break;
  99.       case 'n':
  100.      if (arg[2] == NULL)
  101.      {
  102.         numbering = TRUE;
  103.         break;
  104.      }
  105.      if (arg[3] != NULL)
  106.         goto usage;
  107.      switch (arg[2])
  108.      {
  109.      case 'b':
  110.         print_binaries = FALSE;
  111.         break;
  112.      case 'f':
  113.         folding = FALSE;
  114.         break;
  115.      case 'i':
  116.         interpret = FALSE;
  117.         break;
  118.      case 'n':
  119.         numbering = FALSE;
  120.         break;
  121.      case 'r':
  122.         restart = FALSE;
  123.         break;
  124.      case 'v':
  125.         only_printable = TRUE;
  126.         break;
  127.      default:
  128.         goto usage;
  129.      }
  130.      break;
  131.       case 'r':
  132.      if (arg[2] != NULL)
  133.         goto usage;
  134.      restart = TRUE;
  135.      break;
  136.       case 'v':
  137.      if (arg[2] != NULL)
  138.         goto usage;
  139.      only_printable = FALSE;
  140.      break;
  141.       default:
  142.       usage:
  143.      fprintf(stderr,
  144.          "usage: a2ps [-n{bfinrv}] [-b] [-f] [-i] [-n] [-r] [-v] [f1 f2 ... fn]");
  145.      exit(1);
  146.       }
  147.       arg = argv[++narg];
  148.    }
  149.    if (narg >= argc)
  150.       goto usage;
  151.  
  152.    /* Header printing (postcript prolog) */
  153.    print_header();
  154.  
  155.    /* Print files designated or standard input */
  156.    prefix_width = numbering ? 6 : 1;
  157.    if (narg >= argc)
  158.       print_file("stdin");
  159.    else
  160.    {
  161.       while (narg < argc)
  162.       {
  163.      if (freopen(arg, "r", stdin) == NULL)
  164.      {
  165.         fprintf(stderr, "Error opening %s\n", arg);
  166.         printf("cleanup\n%c",4); /*^D is the reset command for PostScript*/
  167.         exit(1);
  168.      }
  169.      print_file(arg);
  170.      arg = argv[++narg];
  171.       }
  172.    }
  173.  
  174.    printf("cleanup\n%c",4); /*^D is the reset command for Postscript */
  175. }
  176.  
  177. void print_file(name)
  178. char *name;
  179. {
  180.    register int c;
  181.    int start_line, continue_exit;
  182.    int char_width;
  183.  
  184.    /*
  185.     * Printing binary files is not very useful. We stop printing
  186.     * if we detect one of these files. Our heuristic to detect them:
  187.     * if 50% characters of first page are non-printing characters,
  188.     * the file is a binary file.
  189.     * Option -b force binary files impression.
  190.     */
  191.    first_page = TRUE;
  192.    nonprinting_chars = chars = 0;
  193.  
  194.    /*
  195.     * Preprocessing (before printing):
  196.     * - TABs expansion (see interpret option)
  197.     * - FF and BS interpretation
  198.     * - replace non printable characters by a space or a char sequence
  199.     *   like:
  200.     *     ^X for ascii codes < 0x20 (X = [@, A, B, ...])
  201.     *     ^? for del char
  202.     *     M-c for ascii codes > 0x3f
  203.     * - prefix parents and backslash ['(', ')', '\'] by backslash
  204.     *   (escape character in postcript)
  205.     */
  206.    column = 0;
  207.    line = line_number = 0;
  208.    start_line = TRUE;
  209.  
  210.    /*                                  Leslie Spiro 21/10/89
  211.     * Under DOS the file name will contain '\' chars as path seperators, 
  212.     * these need to be double in order to print correctly, so replace 
  213.     * the following line from the original 
  214.    printf("(%s) newfile\n", name);
  215.    * with :
  216.    */
  217.    {
  218.       char *pNextChar = name;
  219.       char Next;
  220.  
  221.       printf("(");
  222.       while (Next = *pNextChar++)
  223.       {
  224.          putchar( Next );
  225.          if (Next=='\\')
  226.          {
  227.             putchar( Next );
  228.          }
  229.       } /*while*/
  230.       printf(") newfile\n", name);
  231.    }
  232.  
  233.  
  234.    if (restart)
  235.       printf("/sheet 1 def\n");
  236.    printf("startpage\n");
  237.  
  238.    c = getchar();
  239.    while (c != EOF)
  240.    {
  241.       /* Form feed */
  242.       if (c == '\f' && interpret)
  243.       {
  244.      if (!start_line)
  245.         printf(") s\n");
  246.      start_line = TRUE;
  247.      printf("endpage startpage\n");
  248.      if (first_page && is_binaryfile(name))
  249.         return;
  250.      line = 0;
  251.      if ((c = getchar()) == EOF)
  252.         break;
  253.       }
  254.  
  255.       /* Start a new line? */
  256.       if (start_line)
  257.       {
  258.      if (numbering)
  259.         printf("(%-5d ", ++line_number);
  260.      else
  261.         printf("( ");
  262.      start_line = FALSE;
  263.       }
  264.  
  265.       /* Interpret each character */
  266.       switch (c)
  267.       {
  268.       case '\b':
  269.      if (!interpret)
  270.         goto print;
  271.      if (column)
  272.         column--;
  273.      putchar(c);
  274.      break;
  275.       case '\n':
  276.      column = 0;
  277.      start_line = TRUE;
  278.      printf(") s\n");
  279.      if (++line >= LINESPERPAGE)
  280.      {
  281.         printf("endpage startpage\n");
  282.         if (first_page && is_binaryfile(name))
  283.            return;
  284.         line = 0;
  285.      }
  286.      break;
  287.       case '\t':
  288.      if (interpret)
  289.      {
  290.         continue_exit = FALSE;
  291.         do
  292.         {
  293.            if (++column + prefix_width > COLUMNSPERLINE)
  294.           if (folding)
  295.           {
  296.              if (fold_line(name) == FALSE)
  297.             return;
  298.           }
  299.           else
  300.           {
  301.              c = cut_line();
  302.              continue_exit = TRUE;
  303.              break;
  304.           }
  305.            putchar(' ');
  306.         } while (column & 0x7);
  307.         if (continue_exit)
  308.            continue;
  309.         break;
  310.         }
  311.       default:
  312.       print:
  313.      if (only_printable)
  314.         char_width = 1;
  315.      else
  316.      {
  317.         char_width = c > 0177 ? 2 : 0;
  318.         char_width += c < ' ' || c == 0177 ? 2 : 1;
  319.      }
  320.      if (prefix_width + (column += char_width) > COLUMNSPERLINE)
  321.         if (folding)
  322.         {
  323.            if (fold_line(name) == FALSE)
  324.           return;
  325.         }
  326.         else
  327.         {
  328.            c = cut_line();
  329.            continue;
  330.         }
  331.      if (c == '(' || c == ')' || c == '\\')
  332.         putchar('\\');
  333.      if (c >= ' ' && c < 0177)
  334.         putchar(c);
  335.      else
  336.      {
  337.         nonprinting_chars++;
  338.         if (only_printable)
  339.            putchar(' ');
  340.         else
  341.         {
  342.            if (c > 0177)
  343.            {
  344.           printf("M-");
  345.           c &= 0177;
  346.            }
  347.            if (c < ' ')
  348.           printf("^%c", c+'@');
  349.            else if (c == 0177)
  350.           printf("^?");
  351.            else
  352.           putchar(c);
  353.         }
  354.      }
  355.      chars++;
  356.      break;
  357.       }
  358.       c = getchar();
  359.    }
  360.  
  361.    if (!start_line)
  362.       printf(") s\n");
  363.    printf("endpage\n");
  364. }
  365.  
  366. int fold_line(name)
  367. char *name;
  368. {
  369.    column = 0;
  370.    printf(") s\n");
  371.    if (++line >= LINESPERPAGE)
  372.    {
  373.       printf("endpage startpage\n");
  374.       if (first_page && is_binaryfile(name))
  375.      return FALSE;
  376.       line = 0;
  377.    }
  378.    if (numbering)
  379.       printf("(      ");
  380.    else
  381.       printf("( ");
  382.  
  383.    return TRUE;
  384. }
  385.  
  386. char cut_line()
  387. {
  388.    char c;
  389.  
  390.    while ((c = getchar()) != EOF && c != '\n' && c != '\f');
  391.    return c;
  392. }
  393.  
  394. is_binaryfile(name)
  395. char *name;
  396. {
  397.    first_page = FALSE;
  398.    /* There is a bug which causes a run time error if the first character
  399.     * in a file is a line feed, I think this is because chars is 0.
  400.     * So as a quick hack disable this check if chars==0 LS 27/11/89
  401.     */
  402.    if (!print_binaries && (chars!=0) && (nonprinting_chars*100/chars) >= 75)
  403.    {
  404.       fprintf(stderr, "%s is a binary file: printing aborted\n", name);
  405.       return TRUE;
  406.    }
  407.    return FALSE;
  408. }
  409.  
  410. print_header()
  411. {
  412.    register int c;
  413.    FILE *f;
  414.    char *string;
  415. #ifdef ANSIC
  416.    time_t date;
  417. #else
  418. #ifdef UNIX
  419.    struct timeval date;
  420.    struct tm *p;
  421. #else
  422. #ifdef SYSV
  423.     struct timeb date;
  424. #endif
  425. #endif
  426. #endif
  427.    char *pFileName=HEADER_PS;
  428.  
  429. #ifdef ANSIC
  430.    /* Get the file name of the post script header file from an environment
  431.     * file, take it from the present directory if nothing defined
  432.     */
  433.    pFileName = getenv("HEADER_PS");
  434.    if (!pFileName)
  435.       pFileName=HEADER_PS;
  436.    /*if*/
  437. #endif
  438.  
  439.    if ((f = fopen(pFileName, "r")) == NULL)
  440.    {
  441.       fprintf(stderr, "Poscript header (%s) missing\n", HEADER_PS);
  442.       exit(1);
  443.    }
  444.  
  445.    /* Header file printing */
  446.    while ((c = getc(f)) != EOF)
  447.       putchar(c);
  448.  
  449.    /* Retrieve date and hour */
  450. #ifdef ANSIC
  451.    if (time(&date) == -1)
  452.    {
  453.       fprintf(stderr, "Error calculing time\n");
  454.       exit(1);
  455.    }
  456.    string = ctime(&date);
  457.  
  458.    /* and print them */
  459.    printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
  460. #else
  461. #ifdef UNIX
  462.    (void) gettimeofday(&date, (struct timezone *)0);
  463.    p = localtime(&date.tv_sec);
  464.    string = asctime(p);
  465.  
  466.    /* and print them */
  467.    printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
  468. #else
  469. #ifdef SYSV
  470.    (void)ftime(&date);
  471.    string = ctime(&date.time);
  472.    printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
  473. #endif
  474. #endif
  475. #endif
  476.  
  477.    /* Go on */
  478.    printf("startdoc\n");
  479. }
  480.