home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 223.lha / AsciiToPostScriptII / a2ps.c < prev    next >
C/C++ Source or Header  |  1989-03-29  |  11KB  |  445 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. /* 2) Ported to the Amiga Jan 24, 1989 (Samuel Paolucci)                */
  13. /*                                                                      */
  14. /************************************************************************/
  15.  
  16. /*
  17.  * Copyright (c) 1988, Miguel Santana, miguel@imag.imag.fr
  18.  *
  19.  * Permission is granted to copy and distribute this file in modified
  20.  * or unmodified form, for noncommercial use, provided (a) this copyright
  21.  * notice is preserved, (b) no attempt is made to restrict redistribution
  22.  * of this file, and (c) this file is not distributed as part of any
  23.  * collection whose redistribution is restricted by a compilation copyright.
  24. */
  25.  
  26.  
  27. #include <stdio.h>
  28. #ifdef ANSIC
  29. #include <time.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. #define PS_EOF          04
  54.  
  55. int fold_line();
  56. void print_file();
  57. char cut_line();
  58.  
  59.  
  60. int column = 0;                 /* Column number (in current line) */
  61. int line = 0;                   /* Line number (in current page) */
  62. int line_number = 0;            /* Source line number */
  63. int first_page;                 /* First page for a file */
  64. int nonprinting_chars, chars;   /* Number of nonprinting and total chars */
  65. int prefix_width;               /* Width in characters for line prefix */
  66. int numbering = TRUE;           /* Line numbering option */
  67. int folding = TRUE;             /* Line folding option */
  68. int restart = TRUE;             /* Restart page number at each file option */
  69. int only_printable = FALSE;     /* Replace non printable char by space option */
  70. int interpret = TRUE;           /* Interpret TAB, FF and BS chars option */
  71. int print_binaries = FALSE;     /* Force printing for binary files */ 
  72.  
  73. main(argc, argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.    int narg;
  78.    char *arg;
  79.  
  80.    /* Option processing */
  81.    arg = argv[narg = 1];
  82.    while (narg < argc && arg[0] == '-')
  83.    {
  84.       switch (arg[1])
  85.       {
  86.       case 'b':
  87.          if (arg[2] != NULL)
  88.             goto usage;
  89.          print_binaries = TRUE;
  90.          break;
  91.       case 'f':
  92.          if (arg[2] != NULL)
  93.             goto usage;
  94.          folding = TRUE;
  95.          break;
  96.       case 'i':
  97.          if (arg[2] != NULL)
  98.             goto usage;
  99.          interpret = TRUE;
  100.          break;
  101.       case 'n':
  102.          if (arg[2] == NULL)
  103.          {
  104.             numbering = TRUE;
  105.             break;
  106.          }
  107.          if (arg[3] != NULL)
  108.             goto usage;
  109.          switch (arg[2])
  110.          {
  111.          case 'b':
  112.             print_binaries = FALSE;
  113.             break;
  114.          case 'f':
  115.             folding = FALSE;
  116.             break;
  117.          case 'i':
  118.             interpret = FALSE;
  119.             break;
  120.          case 'n':
  121.             numbering = FALSE;
  122.             break;
  123.          case 'r':
  124.             restart = FALSE;
  125.             break;
  126.          case 'v':
  127.             only_printable = TRUE;
  128.             break;
  129.          default:
  130.             goto usage;
  131.          }
  132.          break;
  133.       case 'r':
  134.          if (arg[2] != NULL)
  135.             goto usage;
  136.          restart = TRUE;
  137.          break;
  138.       case 'v':
  139.          if (arg[2] != NULL)
  140.             goto usage;
  141.          only_printable = FALSE;
  142.          break;
  143.       default:
  144.       usage:
  145.          fprintf(stderr,
  146.          "usage: a2ps [-n{bfinrv}] [-b] [-f] [-i] [-n] [-r] [-v] [f1 f2 ... fn]\n");
  147.          exit(1);
  148.       }
  149.       arg = argv[++narg];
  150.    }
  151.    if (narg >= argc)
  152.       goto usage;
  153.  
  154.    /* Header printing (postcript prolog) */
  155.    print_header();
  156.  
  157.    /* Print files designated or standard input */
  158.    prefix_width = numbering ? 6 : 1;
  159.    if (narg >= argc)
  160.       print_file("stdin");
  161.    else
  162.    {
  163.       while (narg < argc)
  164.       {
  165.          if (freopen(arg, "r", stdin) == NULL)
  166.          {
  167.             fprintf(stderr, "Error opening %s\n", arg);
  168.             printf("cleanup\n");
  169.             exit(1);
  170.          }
  171.          print_file(arg);
  172.          arg = argv[++narg];
  173.       }
  174.    }
  175.  
  176.    printf("cleanup\n");
  177.  
  178.    putchar(PS_EOF);
  179. }
  180.  
  181. void print_file(name)
  182. char *name;
  183. {
  184.    register int c;
  185.    int start_line, continue_exit;
  186.    int char_width;
  187.  
  188.    /*
  189.     * Printing binary files is not very useful. We stop printing
  190.     * if we detect one of these files. Our heuristic to detect them:
  191.     * if 50% characters of first page are non-printing characters,
  192.     * the file is a binary file.
  193.     * Option -b force binary files impression.
  194.     */
  195.    first_page = TRUE;
  196.    nonprinting_chars = chars = 0;
  197.  
  198.    /*
  199.     * Preprocessing (before printing):
  200.     * - TABs expansion (see interpret option)
  201.     * - FF and BS interpretation
  202.     * - replace non printable characters by a space or a char sequence
  203.     *   like:
  204.     *     ^X for ascii codes < 0x20 (X = [@, A, B, ...])
  205.     *     ^? for del char
  206.     *     M-c for ascii codes > 0x3f
  207.     * - prefix parents and backslash ['(', ')', '\'] by backslash
  208.     *   (escape character in postcript)
  209.     */
  210.    column = 0;
  211.    line = line_number = 0;
  212.    start_line = TRUE;
  213.    printf("(%s) newfile\n", name);
  214.    if (restart)
  215.       printf("/sheet 1 def\n");
  216.    printf("startpage\n");
  217.  
  218.    c = getchar();
  219.    while (c != EOF)
  220.    {
  221.       /* Form feed */
  222.       if (c == '\f' && interpret)
  223.       {
  224.          if (!start_line)
  225.             printf(") s\n");
  226.          start_line = TRUE;
  227.          printf("endpage startpage\n");
  228.          if (first_page && is_binaryfile(name))
  229.             return;
  230.          line = 0;
  231.          if ((c = getchar()) == EOF)
  232.             break;
  233.       }
  234.  
  235.       /* Start a new line? */
  236.       if (start_line)
  237.       {
  238.          if (numbering)
  239.             printf("(%-5d ", ++line_number);
  240.          else
  241.             printf("( ");
  242.          start_line = FALSE;
  243.       }
  244.  
  245.       /* Interpret each character */
  246.       switch (c)
  247.       {
  248.       case '\b':
  249.          if (!interpret)
  250.             goto print;
  251.          if (column)
  252.             column--;
  253.          putchar(c);
  254.          break;
  255.       case '\n':
  256.          column = 0;
  257.          start_line = TRUE;
  258.          printf(") s\n");
  259.          if (++line >= LINESPERPAGE)
  260.          {
  261.             printf("endpage startpage\n");
  262.             if (first_page && is_binaryfile(name))
  263.                return;
  264.             line = 0;
  265.          }
  266.          break;
  267.       case '\t':
  268.          if (interpret)
  269.          {
  270.             continue_exit = FALSE;
  271.             do
  272.             {
  273.                if (++column + prefix_width > COLUMNSPERLINE)
  274.                   if (folding)
  275.                   {
  276.                      if (fold_line(name) == FALSE)
  277.                         return;
  278.                   }
  279.                   else
  280.                   {
  281.                      c = cut_line();
  282.                      continue_exit = TRUE;
  283.                      break;
  284.                   }
  285.                putchar(' ');
  286.             } while (column & 0x7);
  287.             if (continue_exit)
  288.                continue;
  289.             break;
  290.         }
  291.       default:
  292.       print:
  293.          if (only_printable)
  294.             char_width = 1;
  295.          else
  296.          {
  297.             char_width = c > 0177 ? 2 : 0;
  298.             char_width += c < ' ' || c == 0177 ? 2 : 1;
  299.          }
  300.          if (prefix_width + (column += char_width) > COLUMNSPERLINE)
  301.             if (folding)
  302.             {
  303.                if (fold_line(name) == FALSE)
  304.                   return;
  305.             }
  306.             else
  307.             {
  308.                c = cut_line();
  309.                continue;
  310.             }
  311.          if (c == '(' || c == ')' || c == '\\')
  312.             putchar('\\');
  313.          if (c >= ' ' && c < 0177)
  314.             putchar(c);
  315.          else
  316.          {
  317.             nonprinting_chars++;
  318.             if (only_printable)
  319.                putchar(' ');
  320.             else
  321.             {
  322.                if (c > 0177)
  323.                {
  324.                   printf("M-");
  325.                   c &= 0177;
  326.                }
  327.                if (c < ' ')
  328.                   printf("^%c", c+'@');
  329.                else if (c == 0177)
  330.                   printf("^?");
  331.                else
  332.                   putchar(c);
  333.             }
  334.          }
  335.          chars++;
  336.          break;
  337.       }
  338.       c = getchar();
  339.    }
  340.  
  341.    if (!start_line)
  342.       printf(") s\n");
  343.    printf("endpage\n");
  344. }
  345.  
  346. int fold_line(name)
  347. char *name;
  348. {
  349.    column = 0;
  350.    printf(") s\n");
  351.    if (++line >= LINESPERPAGE)
  352.    {
  353.       printf("endpage startpage\n");
  354.       if (first_page && is_binaryfile(name))
  355.          return FALSE;
  356.       line = 0;
  357.    }
  358.    if (numbering)
  359.       printf("(      ");
  360.    else
  361.       printf("( ");
  362.  
  363.    return TRUE;
  364. }
  365.  
  366. char cut_line()
  367. {
  368.    char c;
  369.  
  370.    while ((c = getchar()) != EOF && c != '\n' && c != '\f');
  371.    return c;
  372. }
  373.  
  374. is_binaryfile(name)
  375. char *name;
  376. {
  377.    first_page = FALSE;
  378.    if (!print_binaries && (nonprinting_chars*100 / chars) >= 75)
  379.    {
  380.       fprintf(stderr, "%s is a binary file: printing aborted\n", name);
  381.       return TRUE;
  382.    }
  383.    return FALSE;
  384. }
  385.  
  386. print_header()
  387. {
  388.    register int c;
  389.    FILE *f;
  390.    char *string;
  391. #ifdef ANSIC
  392.    time_t date;
  393. #else
  394. #ifdef UNIX
  395.    struct timeval date;
  396.    struct tm *p;
  397. #else
  398. #ifdef SYSV
  399.     struct timeb date;
  400. #endif
  401. #endif
  402. #endif
  403.  
  404.    if ((f = fopen(HEADER_PS, "r")) == NULL)
  405.    {
  406.       fprintf(stderr, "Postcript header missing\n");
  407.       exit(1);
  408.    }
  409.  
  410.    /* Header file printing */
  411.    while ((c = getc(f)) != EOF)
  412.       putchar(c);
  413.  
  414.    /* Retrieve date and hour */
  415. #ifdef ANSIC
  416.    if (time(&date) == -1)
  417.    {
  418.       fprintf(stderr, "Error calculing time\n");
  419.       exit(1);
  420.    }
  421.    string = ctime(&date);
  422.  
  423.    /* and print them */
  424.    printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
  425. #else
  426. #ifdef UNIX
  427.    (void) gettimeofday(&date, (struct timezone *)0);
  428.    p = localtime(&date.tv_sec);
  429.    string = asctime(p);
  430.  
  431.    /* and print them */
  432.    printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
  433. #else
  434. #ifdef SYSV
  435.    (void)ftime(&date);
  436.    string = ctime(&date.time);
  437.    printf("/date (%.6s %.4s %.8s) def\n", string+4, string+20, string+11);
  438. #endif
  439. #endif
  440. #endif
  441.  
  442.    /* Go on */
  443.    printf("startdoc\n");
  444. }
  445.