home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / cdactual / demobin / share / program / C / APR.ZIP / APR.C
Encoding:
C/C++ Source or Header  |  1979-12-31  |  12.8 KB  |  576 lines

  1. /*
  2.  
  3. NAME
  4.     apr -- source print utility
  5.  
  6. SYNOPSIS
  7.     apr [ -FHbfhlnpst ] [ files ... ]
  8.  
  9. DESCRIPTION
  10.     Apr prints the named files on the stdout. If the file specification
  11.    is '-' or no files were specified, the stdin is assumed. The   
  12.    listing is     separated into pages with the fixed size (user can  
  13.    configure any desired page size). By default, plain pages will be 
  14.    produced, but this option allows to set up either header with file 
  15.    status data and footer with page numbers, or custom header/footer.
  16.    Apr also recognizes text patterns as page-advance     commands. This
  17.    means that a new page will be forced whenever the program     finds
  18.    that pattern at the first column of the input line.
  19.  
  20.  
  21. OPTIONS
  22.     -F <string>    Use <string> as the message to be printed in the footer
  23.         instead of the copyright. Note that this option is ignored if
  24.         -s option is not used.
  25.  
  26.     -H <string>    Use <string> as the message to be printed in the header
  27.         instead of the file name and it's size. Note that this option
  28.         is ignored if -s option is not used.
  29.  
  30.     -b <string> Program will force a new page each time when it finds 
  31.         <string> at the beginning of the input line. Default value of
  32.         <string> is /**.
  33.  
  34.     -f <number> Set the bottom margin to <number> lines (default 2).
  35.  
  36.     -h <number> Set the top margin to <number> lines (default 0).
  37.  
  38.     -l <number> Set the line width to <number> characters (default 78).
  39.  
  40.     -n    Use the form-feed character for new pages (default is newlines).
  41.  
  42.     -p <number>    Set page length to <number> lines (default 72).
  43.  
  44.     -r Provide 6-digit line numbering.
  45.  
  46.     -s Enable headers and footers.
  47.  
  48.     -t <number>    Set tab-size to <number> characters (default 4).
  49.  
  50. FILES
  51.  
  52. VARIABLES
  53.  
  54. CAVEATS
  55.  
  56. SEE ALSO
  57.  
  58. REFERENCES
  59.  
  60. REVISIONS
  61.     10/15/88        Andreo Curko, NightWingers:    tested
  62.     11/14/88        Andreo Curko, NightWingers:    documented
  63.    12/13/88    Tom Sagrak,   NightWingers:   revised for uploading
  64.  
  65. COPYRIGHT
  66.     Copyright (c) 1988 by NightWingers, Zagreb
  67.  
  68.                      Tom Sagrak
  69.                      Draskoviceva 29
  70.                      YU-41000 ZAGREB
  71.                      Yugoslavia
  72.             
  73.     Permission to use, copy, modify, and distribute this
  74.     software and its documentation for any purpose and without
  75.     fee is hereby granted, provided that the above copyright
  76.     notice appears in all copies and that both that copyright
  77.     notice and this permission notice appear in supporting
  78.     documentation, and that the name of NightWingers not be used
  79.     in advertising or publicity pertaining to distribution of 
  80.     the software without specific, written prior permission.
  81.     NightWingers makes no representations about the suitability of
  82.     this software for any purpose.  It is provided "as is"
  83.     without express or implied warranty.
  84.  
  85.    If you find apr of value, and like to use it, a contribution of
  86.    $ 5 or more would be appreciated.
  87.  
  88. */
  89.  
  90. #include <errno.h>
  91. #include <ctype.h>
  92. #include <string.h>
  93. #include <stdio.h>
  94. #include <time.h>
  95. #include <sys/types.h>
  96. #include <sys/stat.h>
  97.  
  98. #ifdef UNIX
  99. #include <sys/timeb.h> 
  100. #endif
  101.  
  102. #ifdef MSDOS
  103. #include <stdlib.h>
  104. #include <process.h>
  105. #include <io.h>
  106. #endif
  107.  
  108. #define TRUE        1
  109. #define FALSE        0
  110. #define OUTPUT        stdout
  111. #define NO_ERRS    0
  112. #define NP_ERR        1
  113. #define USAGE        1
  114.  
  115. #ifdef UNIX
  116. extern int getopt();
  117. extern int optind;
  118. extern char *optarg;
  119. #endif
  120.  
  121.  
  122.  
  123. /**/
  124. #ifdef MSDOS
  125. /*
  126. * name    getopt - parse the command line options, System V style.
  127. *
  128. * synopsis    int getopt(argc, argv, optionS);
  129. *            int argc;       no. of arguments in the command line
  130. *            char *argv[];   argument vector
  131. *            char *optionS;  definition list of options
  132. *            extern int optind;    index of the next argument
  133. *            extern char *optarg;  current option's argument
  134. *
  135. * description    Standard option syntax is:
  136. *                option ::= SW [optLetter] [argLetter space* argument]
  137. *                where
  138. *                - SW is '-'
  139. *                - there is no space before any optLetter or argLetter.
  140. *                - opt/arg letters are alphabetic, not punctuation characters.
  141. *                - optLetter, if present, must be matched in optionS.
  142. *                - argLetters, if present, are found in optionS followed by ':'.
  143. *                - argument is any white-space delimited string.  Note that it
  144. *                  can include the SW character.
  145. *                - upper and lower case letters are distinct.
  146. * returns    (int) ch    - current option if OK
  147. *                        - '?' if error in argument vector
  148. *                        - EOF when no more options
  149. *
  150. **/
  151.  
  152. int    optind    = 1;    /* index of which argument is next    */
  153. char   *optarg;        /* pointer to argument of current option */
  154.  
  155. static    char   *letP;    /* remember next option char's location */
  156. static    char    SW = '-';        /* switch character */
  157.  
  158. int    
  159. getopt(argc,argv,optionS)
  160.     int argc;
  161.     char *argv[], *optionS;
  162. {
  163.     unsigned char ch;
  164.     char *optP;
  165.  
  166.     if (argc > optind) {
  167.         if ((letP = argv[optind]) == NULL || *(letP++) != SW)
  168.             goto gopEOF;
  169.         if (*letP == SW) {
  170.             optind++;
  171.             goto gopEOF;
  172.         }
  173.         if ((ch = *(letP++)) == '\0') {
  174.             optind++;
  175.             goto gopEOF;
  176.         }
  177.         if (ch == ':' ||  (optP = strchr(optionS, ch)) == NULL) {
  178.             optind++;
  179.             goto gopError;
  180.         }
  181.         if (*(++optP) == ':') {
  182.             optind++;
  183.             if (*letP == '\0') {
  184.                 if (argc <= optind)
  185.                     goto  gopError;
  186.                 letP = argv[optind++];
  187.             }
  188.             optarg = letP;
  189.             letP = NULL;
  190.         } 
  191.         else {
  192.             optind++;
  193.             letP = NULL;
  194.             optarg = NULL;
  195.         }
  196.         return ch;
  197.     }
  198. gopEOF:
  199.     optarg = letP = NULL;
  200.     return EOF;
  201.  
  202. gopError:
  203.     optarg = NULL;
  204.     return ('?');
  205. }
  206. #endif
  207.  
  208. /**/
  209. #define LINESIZE 512
  210. #define OPTDEFS "p:l:t:b:h:f:F:H:nsr"        /* program options     */
  211.  
  212. static struct stat statbuf;        /* buffer for a stat info                */
  213. static    FILE *input;               /* current input stream                    */
  214. static char globline[LINESIZE],    /* global buffer for input line            */
  215.             cbrk[] = "/\**",    /* default page-break string            */
  216.             *brkstring,            /* default page-advance string            */
  217.             *foottext,            /* pointer to footer message            */
  218.             *nofile = "(stdin)",/* if no filename specified                */
  219.             *filename,            /* name of file currently printed        */
  220.             *filetime,            /* it's time of the last modification    */
  221.             brkbuf[24],            /* buffer for a page-break string        */
  222.             footbuf[60],        /* buffer for a footer message            */
  223.             headbuf[60];        /* buffer for a header message            */
  224. static int tabsize = 4,            /* de~r}i}i~fault tab width                    */
  225.             brklen = 3,            /* length of page-advance string        */
  226.             footlen = 30,        /* length of the footer message            */
  227.             lines_per_page = 72,/* physical page length in lines        */
  228.             header_margin = 0,    /* default values for header and        */
  229.             footer_margin = 2,    /*    footer margin                        */
  230.             no_ff = TRUE,        /* use <LF> instead of <FF>                */
  231.             line_number = 0,    /* line counter                            */
  232.             do_lnum = FALSE,    /* if set lines will be numbered        */
  233.             A_status = FALSE,    /* if set status lines will be ON        */
  234.             footmessage = FALSE,/* if set user defines footer text        */
  235.             headmessage = FALSE,/* if set user defines header text        */
  236.             linesize = 78,        /* default paper width in chars            */
  237.             paperwidth,            /* info for header() and footer()        */
  238.             ln_cnt,                /* line number in a single input line    */
  239.             page_no;            /* current page number in a stream        */
  240. static long flsize;                /* it's size in bytes                    */
  241.  
  242. static char *copywr = "(C) NightWingers 1988";
  243.  
  244. /**/
  245. #ifdef MSDOS
  246.  
  247. static void 
  248. usage()
  249. {
  250.     fprintf(stderr,"Apr Source Print Utility Version 2.0\n");
  251.     fprintf(stderr,"Copyright (C) NightWingers 1988. All rights reserved.\n");
  252.     fprintf(stderr,"usage: apr [options] [file ...]\n");
  253.     fprintf(stderr,"options: -FHbfhlnpst\n");
  254.     fprintf(stderr," F <string> - redefine footer message (only with -s option)\n");
  255.     fprintf(stderr," H <string> - redefine header message (only with -s option)\n");
  256.     fprintf(stderr," b <string> - redefine page-break string (/\**)\n");
  257.     fprintf(stderr," f <number> - bottom margin in lines (2)\n");
  258.     fprintf(stderr," h <number> - top margin in lines (0)\n");
  259.     fprintf(stderr," l <number> - paper width in characters (78)\n");
  260.     fprintf(stderr," n - use <FF> instead of <nl> for new page (<nl>)\n");
  261.     fprintf(stderr," p <number> - paper size in lines (72)\n");
  262.     fprintf(stderr," r - include line numbers (NO)\n");
  263.     fprintf(stderr," s - output with status (NO)\n");
  264.     fprintf(stderr," t <number> - tab distance in characters (4)\n");
  265.     fprintf(stderr,"example: apr -s -F \"Acct. procs\" -t 8 -h 4 *.awk | lpr");
  266.     exit(USAGE);
  267. }
  268.  
  269. #else
  270.  
  271. static void
  272. usage()
  273. {
  274.     fprintf(stderr,"usage: apr [-FHbfhlnpst] [file ...]\n");
  275.     exit(USAGE);
  276. }
  277.  
  278. #endif
  279.  
  280. /**
  281. * name            header
  282. *
  283. * synopsis        void header();
  284. *        
  285. * description    
  286. *
  287. * return        -*-
  288. *
  289. **/
  290.  
  291. static void
  292. header()
  293. {
  294.     int i = header_margin;
  295.     int g;
  296.     
  297.     while (i--)
  298.         fputc('\n',OUTPUT);
  299.     if (A_status) {
  300.         if (headmessage) {
  301.             g = paperwidth - (strlen(headbuf) + 24);
  302.             fprintf(OUTPUT,"%-s",headbuf);
  303.         }
  304.         else {
  305.             g = (paperwidth - (strlen(filename) + 6 + 24)) >> 1;
  306.             fprintf(OUTPUT,"%-s",filename);
  307.             for (i=0; i<g; i++)
  308.                 fputc(' ',OUTPUT);
  309.             if (flsize)
  310.                 fprintf(OUTPUT,"%-6ld",flsize);
  311.             else
  312.                 fprintf(OUTPUT,"%6s","      ");
  313.         }
  314.         for (i=0; i<g; i++)
  315.             fputc(' ',OUTPUT);
  316.         fprintf(OUTPUT,"%-s",filetime);
  317.         for (i = 0;i < paperwidth;i++)
  318.             fputc('_',OUTPUT);
  319.         fprintf(OUTPUT,"\n\n");
  320.     }
  321.     ln_cnt = lines_per_page - header_margin - footer_margin;
  322. }
  323.  
  324. /**
  325. * name            footer
  326. *
  327. * synopsis        void footer();
  328. *        
  329. * description    
  330. *
  331. * return        -*-
  332. *
  333. **/
  334.  
  335. static void
  336. footer()
  337. {
  338.     int i = footer_margin;
  339.     int j;
  340.     char page_no_str[6];
  341.     
  342.     while (ln_cnt > 0) {
  343.         fputc('\n',OUTPUT);
  344.         ln_cnt--;
  345.     }
  346.     if (A_status) {
  347.         fputc('\n',OUTPUT);
  348.         for (j = 0;j < paperwidth;j++)
  349.             fputc('_',OUTPUT);
  350.         fprintf(OUTPUT,"\n%s", foottext);
  351.         for (j = 0; j < paperwidth-(footlen+5);j++)
  352.             fputc(' ',OUTPUT);
  353.         sprintf(page_no_str,"[%d]",page_no);
  354.         fprintf(OUTPUT,"%5s\n",page_no_str);
  355.     }
  356.     if (no_ff) {
  357.         while (i--)
  358.             fputc('\n',OUTPUT);
  359.     }
  360.     else
  361.         fputc('\f',OUTPUT);
  362.     page_no++;
  363. }
  364.  
  365. /**
  366. *
  367. * name            put_ln
  368. *
  369. * synopsis        void put_ln(line, lin_cnt);
  370. *                char *line;
  371. *                int lin_cnt;
  372. *
  373. * description    
  374. *
  375. * return        -*-
  376. *
  377. **/
  378.  
  379. static void
  380. put_ln(line, lin_cnt)
  381.     char *line;
  382.     int lin_cnt;
  383. {
  384.     char c;
  385.     register i,j;
  386.  
  387.     for(i=0;i<lin_cnt;i++) {
  388.         if(ln_cnt <= 0)
  389.             header();
  390.         if (do_lnum) {
  391.             if (i == 0) {
  392.                 line_number++;
  393.                 fprintf(OUTPUT,"%-6d:   ",line_number);
  394.             }
  395.             else
  396.                 fprintf(OUTPUT,"      :   ");
  397.         }
  398.         for(j=0;j<linesize && *line;j++) {
  399.             c = *line++;
  400.             fputc(c,OUTPUT);
  401.         }
  402.         if (c != '\n')
  403.             fputc('\n',OUTPUT);
  404.         ln_cnt--;
  405.         if(ln_cnt <= 0)
  406.             footer();
  407.     }
  408. }
  409.  
  410. /**
  411. *
  412. * name            do_ln 
  413. *
  414. * synopsis        void do_ln(line);
  415. *                char *line;
  416. *
  417. * description    
  418. *
  419. * return        -*-
  420. *
  421. **/
  422.  
  423. static void
  424. do_ln(line)
  425.     char *line;
  426. {
  427.     static char buf[512];
  428.     static char *p;
  429.     int cnt = 1;
  430.  
  431.     p = buf;
  432.     if ( ! strncmp(brkstring,line,brklen)) {
  433.         if (ln_cnt > 0)
  434.             footer();
  435.     }
  436.     while(*line) {
  437.         if(*line == '\t') {
  438.             do{
  439.                 *p++ = ' ';
  440.             } while(cnt++ % tabsize != 0);
  441.             ++line;
  442.         }
  443.         else {
  444.             ++cnt;
  445.             *p++ = *line++;
  446.         }
  447.     }
  448.     *p = '\0';
  449.     cnt = strlen(buf);
  450.     put_ln(buf, 1 + cnt/(linesize+1));
  451. }
  452.  
  453. static void
  454. do_file()
  455. {
  456.     char *l;
  457.     page_no = 1;
  458.     ln_cnt = line_number = 0;
  459.     while((l = fgets(globline, LINESIZE, input)) != NULL)
  460.         do_ln(l);
  461.     footer();
  462. }
  463.  
  464. /**/
  465. void
  466. main(argc, argv)
  467.   int argc;
  468.   char *argv[];
  469. {
  470.     int ch;
  471.     int pom;
  472.  
  473.     brkstring = cbrk;
  474.     while ((ch = getopt(argc,argv,OPTDEFS)) != EOF ) {
  475.         switch(ch) {
  476.             case 'l':
  477.                 pom = atoi(optarg);
  478.                 if (pom >= 40 && pom <= 255)
  479.                     linesize = pom;
  480.                 break;
  481.             case 't':
  482.                 pom = atoi(optarg);
  483.                 if (pom > 0 && pom <= 20)
  484.                     tabsize = pom;
  485.                 break;
  486.             case 'p':
  487.                 pom = atoi(optarg);
  488.                 if (pom >= 20) {
  489.                     if (A_status)
  490.                         lines_per_page = pom - 6;
  491.                     else
  492.                         lines_per_page = pom;
  493.                 }
  494.                 break;
  495.             case 'h':
  496.                 pom = atoi(optarg);
  497.                 if (pom >= 0 && pom <= 20)
  498.                     header_margin = pom;
  499.                 break;
  500.             case 'f':
  501.                 pom = atoi(optarg);
  502.                 if (pom >= 0 && pom <= 20)
  503.                     footer_margin = pom;
  504.                 break;
  505.             case 'n':
  506.                 no_ff = FALSE;
  507.                 break;
  508.             case 'r':
  509.                 do_lnum = TRUE;
  510.                 break;
  511.             case 's':
  512.                 if (! A_status)
  513.                     lines_per_page -= 6;
  514.                 A_status = TRUE;
  515.                 break;
  516.             case 'b':
  517.                 strcpy(brkbuf, optarg);
  518.                 brkstring = brkbuf;
  519.                 brklen = strlen(brkstring);
  520.                 break;
  521.             case 'F':
  522.                 strcpy(footbuf, optarg);
  523.                 footmessage = TRUE;
  524.                 break;
  525.             case 'H':
  526.                 strcpy(headbuf, optarg);
  527.                 headmessage = TRUE;
  528.                 break;
  529.             case '?':
  530.                 usage();
  531.                 break;
  532.         }
  533.     }
  534.     paperwidth = linesize;
  535.     if (do_lnum)
  536.         linesize -= 10;
  537.     if (footmessage) {
  538.         footlen = strlen(footbuf);
  539.         foottext = footbuf;
  540.     }
  541.     else {
  542.         foottext = copywr;
  543.     }
  544.     if (optind == argc) {                /* stdin */
  545.         filename = nofile;
  546.         time(&flsize);    
  547.         filetime = ctime(&flsize);
  548.         flsize = 0L;
  549.         input = stdin;
  550.         do_file();
  551.     }
  552.     else {
  553.         for(; optind<argc; ++optind) {
  554.             filename = argv[optind];
  555.             if (stat(argv[optind], &statbuf) == EOF) {
  556.                 perror(argv[optind]);
  557.                 exit(ENOENT);
  558.             }
  559.             if (!(statbuf.st_mode & 0x8000)) {
  560.                 fprintf(stderr,"%s: not an ordinary file\n",filename);
  561.                 exit(NP_ERR);
  562.              }
  563.             flsize = statbuf.st_size;
  564.             filetime = ctime(&(statbuf.st_mtime));
  565.             if((input = fopen(argv[optind], "r")) == NULL) {
  566.                 perror(argv[optind]);
  567.                 exit(EACCES);
  568.             }
  569.             do_file();
  570.         }
  571.     }
  572.     exit(NO_ERRS);
  573. }