home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / INTER32C.ZIP / INTPRINT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-12  |  37.8 KB  |  1,449 lines

  1. /************************************************************************/
  2. /* INTPRINT.C by Ralf Brown.  Donated to the Public Domain.        */
  3. /* Please do not remove my name from any copies or derivatives.        */
  4. /************************************************************************/
  5. /* Program History:                            */
  6. /*   v1.00  4/23/89  initial public release                */
  7. /*             with 4/30/89 list                    */
  8. /*   v1.10  5/21/89  added -I and -f                    */
  9. /*   v1.11  1/6/90   fixed #endif's for compilers which don't handle    */
  10. /*             labels                        */
  11. /*   v1.20  6/8/90   added -r                        */
  12. /*   v1.30  7/14/90  added -b, tables now stay aligned on odd indents    */
  13. /*   v1.40  10/6/90  added -B based on changes by Naoto Kimura, -w    */
  14. /*   v1.40a 5/6/91   HP LaserJet II support by Russ Herman        */
  15. /*   v1.41  7/9/91   HP PCL support by P.J.Farley III            */
  16. /*   v2.00  9/1/91   modular printer definitions            */
  17. /*             printing multipart interrupt list            */
  18. /*   v2.01  2/9/92   fixed summary entry for non-numeric AX= and AH=    */
  19. /*             smarter page breaks                */
  20. /*   v2.02  2/18/92  bugfix & isxdigit suggested by Aaron West        */
  21. /*   v2.10  3/14/92  updated to handle extra flags in headings        */
  22. /*   v2.11  5/23/92  bugfix pointed out by Joe White            */
  23. /*   v2.20  6/12/92  added -F based on code by Richard Brittain     */
  24. /*             added -H and Panasonic printer def by Lewis Paper    */
  25. /************************************************************************/
  26. /* Recompiling:                                */
  27. /*   Turbo C / Borland C++                        */
  28. /*    tcc -mt -lt -Z -p intprint                    */
  29. /************************************************************************/
  30.  
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <ctype.h>
  34.  
  35. #define VERSION "2.20"
  36.  
  37. #ifdef __TURBOC__
  38. #  define PROTOTYPES
  39. #  include <stdlib.h>
  40.    int _Cdecl isatty(int handle) ;
  41.    void _setenvp(void) {} /* don't need the environment, so don't include it */
  42. #else
  43.  
  44. /* not Turbo C / Borland C, so set configuration #defines */
  45. #if 0  /* set to 1 if compiler supports ANSI-style prototypes, 0 otherwise */
  46. #define PROTOTYPES
  47. #endif
  48. #if 1  /* set to 0 if library contains strnicmp(), 1 otherwise */
  49. #define NEED_STRNICMP
  50. #endif
  51. #if 1  /* set to 0 if library contains isxdigit(), 1 otherwise */
  52. #define NEED_ISXDIGIT
  53. #endif
  54. #if 0  /* set to 0 if library contains strdup(), 1 otherwise */
  55. #define NEED_STRDUP
  56. #endif
  57. #if 1  /* set to 0 if library contains strupr(), 1 otherwise */
  58. #define NEED_STRUPR
  59. #endif
  60.  
  61. #define _Cdecl
  62.  
  63. char *itoa(num,buf,radix)   /* not everybody has the same itoa() as TurboC */
  64. int num ;            /* minimal implementation */
  65. char *buf ;
  66. int radix ;
  67. {
  68.    int count = 0 ;
  69.    int i ; 
  70.    char tmp ;
  71.  
  72.    do {
  73.       buf[count++] = '0' + num % radix ;
  74.       num = num / radix ;
  75.    } while (num) ;
  76.    buf[count] = '\0' ;
  77.    if (count > 1)
  78.       for (i = 0 ; i < count / 2 ; i++)
  79.      {
  80.      tmp = buf[i] ;
  81.      buf[i] = buf[count-i-1] ;
  82.      buf[count-i-1] = tmp ;
  83.      }
  84.    return buf ;
  85. }
  86. #endif /* __TURBOC__ */
  87.  
  88. #ifndef FALSE
  89. #define FALSE 0
  90. #endif
  91. #ifndef TRUE
  92. #define TRUE !FALSE
  93. #endif
  94.  
  95. #define MAXLINE 81   /* at most 80 chars per line (plus newline) */
  96. #define MAXPAGE 200  /* at most 200 lines per page */
  97.  
  98. #define start_of_entry(s) (strncmp(s,"INT ",4) == 0)
  99.  
  100. /***********************************************/
  101.  
  102. typedef struct _cstr         /* a counted string */
  103.    {
  104.    int len ;             /* the string's length */
  105.    char *str ;             /* the actual contents of the string */
  106.    } cstr ;
  107.  
  108. #define CSTR(s) { sizeof(s)-1, (s) }  /* for defining a counted string literal */
  109. #define cstrlen(s) ((s)->len)     /* how long is the counted string? */
  110. #define cstrchar(s,i) ((s)->str[i])  /* retrieve a character from a counted string */
  111.  
  112. typedef struct _printer_def
  113.    {
  114.    char *name ;            /* for selecting the appropriate printer */
  115.    cstr init1, init2 ;        /* initialization strings */
  116.    cstr marginl, marginc, marginr ; /* margins: duplex even, non-duplex, duplex odd */
  117.    cstr duplex_on ;        /* turn on duplex mode */
  118.    cstr term1, term2 ;        /* cleanup strings */
  119.    cstr bold_on, bold_off ;    /* boldface on/off */
  120.    int indent ;            /* how many extra spaces to indent */
  121.    int lines_per_page ;        /* how many lines to print on each page */
  122.    int page_length ;        /* how many lines on each page */
  123.    int page_width ;        /* how many printable columns per line? */
  124. #ifdef PROTOTYPES
  125.    void (*put_line)(FILE *,int) ;/* function to call to print out divider line */
  126. #else
  127.    void (*put_line)() ;        /* function to call to print out divider line */
  128. #endif /* PROTOTYPES */
  129.    int *flag ;            /* flag to set when using this printer definition */
  130.    } PRINTER_DEF ;
  131.  
  132. struct filter_list
  133.    {
  134.    struct filter_list *next ;
  135.    char *str ;
  136.    } ;
  137.  
  138. typedef struct _header
  139.    {
  140.    int part ;
  141.    int first_on_page ; /* TRUE if a new entry starts at the top of the page */
  142.    char desc[24] ;
  143.    } HEADER ;
  144.  
  145. /***********************************************/
  146.  
  147. #ifdef PROTOTYPES
  148. void usage(void) ;
  149. void fatal(char *msg) ;
  150. void get_raw_line(char *buf,int size) ;
  151. int unwanted_section(char *buf) ;
  152. void get_line(char *buf,int size) ;
  153. void indent_line(FILE *fp) ;
  154. void indent_to(int where,FILE *fp) ;
  155. void put_line(FILE *fp, int len) ;
  156. void HPPCL_put_line(FILE *fp, int len) ;
  157. void fputcstr(cstr *s, FILE *fp) ;
  158. int divider_line(char *line) ;
  159. int section_start(char *line) ;
  160. void output_line(char *line,FILE *fp) ;
  161. void fill_buffer(int lines, int lines_per_page) ;
  162. int find_page_break(int lines) ;
  163. void summarize(FILE *summary, int line, int pages_printed) ;
  164. void start_format(char *line) ;
  165. struct filter_list *add_filter_info(struct filter_list *list,char *str) ;
  166. void build_filter_lists(char *file) ;
  167. void print_line(char *line) ;
  168. void make_description(char *desc,int line) ;
  169. char *determine_heading(int last) ;
  170. void print_buffer(int last, int lines_per_page, int total_lines, int use_FF) ;
  171. void select_printer(char *name) ;
  172. void display_printers(void) ;
  173. int _Cdecl main(int argc, char **argv) ;
  174. #else
  175. void put_line() ;
  176. void HPPCL_put_line() ;
  177. #endif /* PROTOTYPES */
  178.  
  179. /***********************************************/
  180.  
  181. FILE *infile, *outfile ;
  182. char *input_file ;
  183.  
  184. char buffer[MAXPAGE][MAXLINE] ;
  185. char num[6] ;
  186. char summary_line[2*MAXLINE] ;
  187.  
  188. int pages_printed = 0 ;
  189. int page_width = 0 ;        /* page width in characters, 0 = use prtdef */
  190. int indent = 0 ;        /* number of blanks to add at start of each line */
  191. int widow_length = 10 ;        /* number of lines to scan for good place to break */
  192. int page_numbers = FALSE ;    /* add page numbers to bottom of page? */
  193. int multi_file = FALSE ;    /* printing multipart interrupt list? */
  194. int out_of_files = FALSE ;    /* hit end of last file for multipart printing? */
  195. int do_summary = FALSE ;    /* create a one-line-per-call summary? */
  196. int do_formats = FALSE ;    /* create a separate file with data structures? */
  197. int do_filter = FALSE ;        /* using a filtering file? */
  198. int do_headers = FALSE ;    /* add page headings? */
  199. int IBM_chars = FALSE ;        /* printer can handle IBM graphics characters */
  200. int boldface = FALSE ;        /* boldface titles and Return:/Notes: ? */
  201. int printer_bold = FALSE ;    /* boldface using printer control sequences? */
  202. int echo_format = FALSE ;
  203. int duplex = FALSE ;
  204. int HPPCL_mode = FALSE ;
  205. FILE *summary ;
  206. FILE *formats ;
  207. PRINTER_DEF *printer = NULL ;
  208.  
  209. int first_page = 0 ;
  210. int last_page = 9999 ;
  211.  
  212. struct filter_list *includes = NULL ;
  213. struct filter_list *excludes = NULL ;
  214.  
  215. HEADER header_first = { 0, FALSE, "" } ;
  216. HEADER header_last = { 0, FALSE, "" } ;
  217.  
  218. /***********************************************/
  219.  
  220. PRINTER_DEF printers[] =
  221.    {
  222.      { "default",
  223.        CSTR(""), CSTR(""),
  224.        CSTR(""), CSTR(""), CSTR(""),
  225.        CSTR(""),
  226.        CSTR(""), CSTR(""),
  227.        CSTR(""), CSTR(""),
  228.        -1,
  229.        60,
  230.        0,
  231.        79,
  232.        put_line,
  233.        NULL,
  234.      },
  235.      { "Epson FX80, 12 cpi",
  236.        CSTR("\033M"), CSTR(""),
  237.        CSTR("\033l\004"), CSTR("\033l\007"), CSTR("\033l\014"),
  238.        CSTR(""),
  239.        CSTR("\033P"), CSTR("\033l\000"),
  240.        CSTR("\033E"), CSTR("\033F"),
  241.        0,
  242.        60,
  243.        0,
  244.        87,    /* 96 - left margin - 1 right margin */
  245.        put_line,
  246.        NULL,
  247.      },
  248.      { "Panasonic KX-P1124i / 10 cpi Epson",
  249.        CSTR(""), CSTR(""),
  250.        CSTR(""), CSTR(""), CSTR(""),
  251.        CSTR(""),
  252.        CSTR(""), CSTR(""),
  253.        CSTR("\033E"), CSTR("\033F"),
  254.        -1,
  255.        60,
  256.        0,
  257.        79,
  258.        put_line,
  259.        NULL,
  260.      },
  261.      { "HP PCL",
  262.        CSTR("\033(8U"), CSTR(""),
  263.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  264.        CSTR("\033&l1S"),
  265.        CSTR("\033E"), CSTR(""),
  266.        CSTR("\033(s3B"), CSTR("\033(s0B"),
  267.        0,
  268.        69,
  269.        0,
  270.        87,    /* 96 - left margin - 1 right margin */
  271.        HPPCL_put_line,
  272.        &HPPCL_mode,
  273.      },
  274. #define HPPCL_FONT_ON_A "\033(s0p12h10v0s0b"
  275. /* HP PCL4/5 Font select: Roman-8;Upright12Pitch10PointMediumWeight */
  276. #define HPPCL_FONT_ON_B "T\033&l6.8571C"
  277. /* HP PCL4/5 Font select: End typeface select;VMI=7LPI: (48/7)-48th's inches*/
  278. #define HPPCL_IBM_LN_A    "\033&f0S\033*p-15Y\033*c"
  279. /* HP PCL4/5 IBM Line:    Push Pos;Up 15/720";Hor.Rule ???/300ths" long */
  280. #define HPPCL_IBM_LN_B    "a3b0P\033&f1S"
  281. /* HP PCL4/5 IBM Line:     3/300ths" high,Print rule;Pop Position */
  282.      { "LaserJet II",
  283.        CSTR("\033(10U"),CSTR(""),
  284.        CSTR("\033&a4c4L"), CSTR("\033&a8c8L"), CSTR("\033&a12c12L"),
  285.        CSTR(""),
  286.        CSTR("\033E"),CSTR(""),
  287.        CSTR("\033(s3B"),CSTR("\033(s0B"),
  288.        0,
  289.        54,
  290.        60,
  291.        79,
  292.        put_line,
  293.        &IBM_chars,
  294.      },
  295.    } ;
  296. #define NUM_PRINTERS (sizeof(printers)/sizeof(printers[0]))
  297.  
  298. /***********************************************/
  299.  
  300. #ifdef NEED_STRNICMP
  301. #ifdef PROTOTYPES
  302. int strnicmp(char *s1,char *s2,int len)
  303. #else
  304. int strnicmp(s1,s2,len)
  305. char *s1,*s2 ;
  306. unsigned int len ;
  307. #endif PROTOTYPES
  308. {
  309.    char c1, c2 ;
  310.  
  311.    while (*s1 && *s2 && len > 0)
  312.       {
  313.       len-- ;
  314.       c1 = (islower(*s1) ? toupper(*s1) : *s1) ;
  315.       c2 = (islower(*s2) ? toupper(*s2) : *s2) ;
  316.       if (c1 != c2 || len == 0)     /* mismatch or substrings exhausted? */
  317.      return (c1 - c2) ;
  318.       s1++ ;
  319.       s2++ ;
  320.       }
  321.    return 0 ;  /* strings match exactly on first 'len' characters */
  322. }
  323. #endif /* NEED_STRNICMP */
  324.  
  325. #ifdef NEED_STRUPR
  326. #ifdef PROTOTYPES
  327. char *strupr(char *s)
  328. #else
  329. char *strupr(s)
  330. char *s ;
  331. #endif /* PROTOTYPES */
  332. {
  333.    char *orig_s = s ;
  334.    char c ;
  335.    
  336.    if (s)
  337.       while (*s)
  338.      {
  339.      c = *s ;      
  340.      *s++ = (islower(c) ? toupper(c) : c) ;
  341.      }
  342.    return orig_s ;
  343. }
  344. #endif /* NEED_STRUPR */
  345.  
  346. #ifdef NEED_STRDUP
  347. #ifdef PROTOTYPES
  348. char *strdup(char *s)
  349. #else
  350. char *strdup(s)
  351. char *s ;
  352. #endif /* PROTOTYPES */
  353. {
  354.    char *copy ;
  355.       
  356.    if (s)
  357.       copy = (char *)malloc(strlen(s)+1) ;
  358.    else
  359.       copy = NULL ;   
  360.    if (copy)
  361.       strcpy(copy,s) ;
  362.    return copy ;
  363. }
  364. #endif /* NEED_STRDUP */
  365.  
  366. #ifdef NEED_ISXDIGIT
  367. #ifdef PROTOTYPES
  368. int isxdigit(int c)
  369. #else
  370. int isxdigit(c)
  371. int c ;
  372. #endif /* PROTOTYPES */
  373. {
  374.    return isdigit(c) || (strchr("ABCDEFabcdef",c) != NULL) ;
  375. }
  376. #endif /* NEED_ISXDIGIT */
  377.  
  378. /***********************************************/
  379.  
  380. void usage()
  381. {
  382.    fputs("\nUsage: intprint [options] intlist [>|>>]output\n",stderr) ;
  383.    fputs("Options:\n",stderr) ;
  384.    fputs("\t-b\tboldface title lines and Return:/Note:\n",stderr) ;
  385.    fputs("\t-B\tboldface using printer control codes instead of overprinting\n",stderr) ;
  386.    fputs("\t-d\t(duplex) print even/odd pages with different indents\n",stderr) ;
  387.    fputs("\t-e\tassume 'elite' mode (96 chars per line) for default printer\n",stderr) ;
  388.    fputs("\t-ffile\twrite all data structure formats to 'file'\n",stderr) ;
  389.    fputs("\t-Ffile\tprint only entries matching filtering info in 'file'\n",stderr);
  390.    fputs("\t-H\tadd page headers\n",stderr) ;
  391.    fputs("\t-iN\tindent output N spaces (overridden by some printers)\n",stderr) ;
  392.    fputs("\t-I\tprinter supports IBM graphics characters\n",stderr) ;
  393.    fputs("\t-lN\tprint N lines per page (default depends on printer)\n",stderr) ;
  394.    fputs("\t-LN\tassume N lines on a page, use linefeeds if > #lines printed\n",stderr) ;
  395.    fputs("\t-m\tlist is in multiple parts starting with the named file\n",stderr) ;
  396.    fputs("\t-nN\tassume N pages have been printed from previous parts\n",stderr) ;
  397.    fputs("\t-p\tadd page numbers\n",stderr) ;
  398.    fputs("\t-Pname\tassume printer 'name' (-P? lists supported printers)\n",stderr) ;
  399.    fputs("\t-rN:M\tprint only pages N through M\n",stderr) ;
  400.    fputs("\t-sfile\twrite a one-line-per-function summary to 'file'\n",stderr) ;
  401.    fputs("\t-tN\tselect typeface N for the chosen printer\n",stderr) ;
  402.    fputs("\t-wN\tscan N lines from bottom of page for good place to break\n",stderr) ;
  403.    exit(1) ;
  404. }
  405.  
  406. /***********************************************/
  407.  
  408. void fatal(msg)
  409. char *msg ;
  410. {
  411.    fputs(msg,stderr) ;
  412.    fputs("\n",stderr) ;
  413.    exit(1) ;
  414. }
  415.  
  416. /***********************************************/
  417.  
  418. void indent_line(fp)
  419. FILE *fp ;
  420. {
  421.    int ind = indent ;
  422.  
  423.    while (ind >= 8)
  424.       {
  425.       fputc('\t',fp) ;
  426.       ind -= 8 ;
  427.       }
  428.    while (ind-- > 0)
  429.       fputc(' ', fp) ;
  430. }
  431.  
  432. /***********************************************/
  433.  
  434. void indent_to(where,fp)
  435. int where ;
  436. FILE *fp ;
  437. {
  438.    indent_line(fp) ;
  439.    while (where-- > 0)
  440.       fputc(' ', fp) ;
  441. }
  442.  
  443. /***********************************************/
  444.  
  445. void put_line(fp,len)
  446. FILE *fp ;
  447. int len ;
  448. {
  449.    int i ;
  450.  
  451.    if (IBM_chars)
  452.       for (i = 0 ; i < len ; i++)
  453.      fputc(196,fp) ;  /* single horizontal line */
  454.    else
  455.       for (i = 0 ; i < len ; i++)
  456.      fputc('-',fp) ;
  457. }
  458.  
  459. /***********************************************/
  460.  
  461. void HPPCL_put_line(fp,len)
  462. FILE *fp ;
  463. int len ;
  464. {
  465.    fputs(HPPCL_IBM_LN_A,fp) ;
  466.    itoa((len * 25), num, 10) ;
  467.    fputs(num,fp) ;
  468.    fputs(HPPCL_IBM_LN_B,fp) ;
  469. }
  470.  
  471. /***********************************************/
  472.  
  473. void fputcstr(s,fp)        /* output the counted string to the given file */
  474. FILE *fp ;
  475. cstr *s ;
  476. {
  477.    int i ;
  478.  
  479.    for (i = 0 ; i < cstrlen(s) ; i++)
  480.       fputc(cstrchar(s,i),fp) ;
  481. }
  482.  
  483. /***********************************************/
  484.  
  485. int divider_line(line)
  486. char *line ;
  487. {
  488.    return strncmp(line,"--------",8) == 0 ;
  489. }
  490.  
  491. /***********************************************/
  492.  
  493. int section_start(line)
  494. char *line ;
  495. {
  496.    if (strncmp(line,"Return:",7) == 0 ||
  497.        strncmp(line,"Desc:",5) == 0 ||
  498.        strncmp(line,"Note:",5) == 0 ||
  499.        strncmp(line,"Notes:",6) == 0 ||
  500.        strncmp(line,"SeeAlso:",8) == 0 ||
  501.        strncmp(line,"BUG:",4) == 0 ||
  502.        strncmp(line,"Program:",8) == 0)
  503.       return 1 ;
  504.    return 0 ;
  505. }
  506.  
  507. /***********************************************/
  508.  
  509. void output_line(line,fp)
  510. char *line ;
  511. FILE *fp ;
  512. {
  513.    int pos = 0 ;
  514.    char bold[10] ;
  515.  
  516.    if (boldface)
  517.       {
  518.       if (start_of_entry(line) || strncmp(line,"Format of ",10) == 0 ||
  519.       strncmp(line,"Values ",7) == 0)
  520.      {
  521.      indent_line(fp) ;
  522.      if (printer_bold)
  523.         {
  524.         fputcstr(&printer->bold_on,fp) ;
  525.         fputs(line,fp) ;
  526.         fputcstr(&printer->bold_off,fp) ;
  527.         line = NULL ;
  528.         }
  529.      else
  530.         {
  531.         fputs(line,fp) ;
  532.         fputc('\r',fp) ;
  533.         }
  534.      }
  535.       else if (section_start(line))
  536.      {
  537.      strncpy(bold,line,sizeof bold) ;
  538.      *strchr(bold,':') = '\0' ;
  539.      indent_line(fp) ;
  540.      if (printer_bold)
  541.         {
  542.         fputcstr(&printer->bold_on,fp) ;
  543.         fputs(bold,fp) ;
  544.         fputcstr(&printer->bold_off,fp) ;
  545.         pos = strlen(bold) ;     /* we're no longer at the left edge of the */
  546.         line += pos ;         /* line, so figure out where we are */
  547.         }
  548.      else
  549.         {
  550.         fputs(bold,fp) ;
  551.         fputc('\r',fp) ;
  552.         }
  553.      }
  554.       }
  555.    if (line && *line)
  556.       {
  557.       if (pos == 0)        /* are we currently at the left edge of the line? */
  558.      indent_line(fp) ;  /* if yes, indent the desired amount */
  559.       if (indent % 8)
  560.      {
  561.      while (*line)
  562.         {
  563.         if (*line == '\t')
  564.            do {
  565.           fputc(' ',fp) ;
  566.           } while (++pos % 8) ;
  567.         else
  568.            {
  569.            fputc(*line,fp) ;
  570.            pos++ ;
  571.            }
  572.         line++ ;
  573.         }
  574.      }
  575.       else
  576.      fputs(line,fp) ;
  577.       }
  578.    fputc('\n',fp) ;
  579. }
  580.  
  581. /***********************************************/
  582.  
  583. void get_raw_line(buf,size)
  584. char *buf ;
  585. int size ;
  586. {
  587.    int last ;
  588.  
  589.    buf[0] = '\0' ;
  590.    if (out_of_files)
  591.       return ;
  592.    fgets(buf,size,infile) ;
  593.    if ((feof(infile) || buf[0] == '\0'))
  594.       if (multi_file)
  595.      {
  596.      FILE *tempfile ;
  597.  
  598.      last = strlen(input_file) - 1 ;
  599.      input_file[last]++ ;
  600.      if ((tempfile = fopen(input_file,"r")) != NULL)
  601.         {
  602.         fclose(infile) ;
  603.         infile = tempfile ;
  604.         fgets(buf,size,infile) ;
  605.         }
  606.      else
  607.         {
  608.         out_of_files = TRUE ;
  609.         return ;
  610.         }
  611.      }
  612.       else
  613.      out_of_files = TRUE ;
  614.    last = strlen(buf) - 1 ;
  615.    if (last < 0)
  616.       last = 0 ;
  617.    if (buf[last] == '\n')
  618.       buf[last] = '\0' ;  /* strip the newline */
  619. }
  620.  
  621. /***********************************************/
  622.  
  623. int unwanted_section(buf)
  624. char *buf ;
  625. {
  626.    int unwanted = FALSE ;
  627.    int found ;
  628.    char str[MAXLINE] ;
  629.    struct filter_list *p ;
  630.    
  631.    if (start_of_entry(buf)) /* is it an interrupt entry? */
  632.       {
  633.       strncpy(str,buf,sizeof str) ;
  634.       str[sizeof str - 1] = '\0' ;
  635.       (void) strupr(str) ;
  636.       /* set 'unwanted' to TRUE if *any* exclude string matches */
  637.       for (p = excludes ; p ; p = p->next)
  638.      {
  639.      if (p->str && strstr(str, p->str) != NULL)
  640.         {
  641.         unwanted = TRUE ;
  642.         break ;
  643.         }
  644.      }
  645.       /* if still wanted, set to TRUE if *no* include string matches */
  646.       if (!unwanted)
  647.      {
  648.      found = FALSE ;
  649.      for (p = includes ; p ; p = p->next)
  650.         {
  651.         if (p->str && strstr(str, p->str) != NULL)
  652.            {
  653.            found = TRUE ;
  654.            break ; 
  655.            }
  656.         }
  657.      if (!found)
  658.         unwanted = TRUE ;
  659.      }
  660.       }
  661.    return unwanted ;
  662. }
  663.  
  664. /***********************************************/
  665.  
  666. void get_line(buf,size)
  667. char *buf ;
  668. int size ;
  669. {
  670.    static char next_line[MAXLINE] ;
  671.    static int readahead = FALSE ;
  672.  
  673.    /* get the next line from the file, skipping unwanted entries */
  674.    if (readahead)
  675.       {
  676.       strncpy(buf,next_line,size) ;
  677.       buf[size-1] = '\0' ;
  678.       readahead = FALSE ;
  679.       }
  680.    else
  681.       {
  682.       get_raw_line(buf,size) ;
  683.       strncpy(next_line,buf,sizeof next_line);
  684.       next_line[sizeof next_line - 1] = '\0' ;
  685.       /* if we read a divider line, we have to look ahead */
  686.       while (do_filter && next_line[0] && divider_line(next_line))
  687.      {
  688.      strncpy(buf,next_line,size) ; /* we may be returning the divider */
  689.      buf[size-1] = '\0' ;
  690.      get_raw_line(next_line,sizeof next_line) ;
  691.      if (unwanted_section(next_line))
  692.         {
  693.         while (!divider_line(next_line))
  694.            get_raw_line(next_line,sizeof next_line) ;
  695.         }
  696.      else /* section is wanted, so return divider and then next line */
  697.         readahead = TRUE ;
  698.      }
  699.       }
  700. }
  701.  
  702. /***********************************************/
  703.  
  704. void fill_buffer(lines,lines_per_page)
  705. int lines, lines_per_page ;
  706. {
  707.    int i ;
  708.  
  709.    if (lines)
  710.       for (i = lines ; i < lines_per_page ; i++)
  711.      strcpy(buffer[i-lines], buffer[i]) ;
  712.    else
  713.       lines = lines_per_page ;
  714.    for (i = lines_per_page - lines ; i < lines_per_page ; i++)
  715.       get_line(buffer[i], sizeof(buffer[i])) ;
  716. }
  717.  
  718. /***********************************************/
  719.  
  720. int find_page_break(lines)
  721. int lines ;
  722. {
  723.    int i ;
  724.  
  725.    for (i = 0 ; i < widow_length ; i++)
  726.       {
  727.       if (strcmp(buffer[lines-i-1],"\n") == 0 ||
  728.       strlen(buffer[lines-i-1]) == 0 ||
  729.       divider_line(buffer[lines-i-1]) ||
  730.       section_start(buffer[lines-i]))
  731.      return lines - i ;
  732.       }
  733.    return lines ;
  734. }
  735.  
  736. /***********************************************/
  737.  
  738. void summarize(summary, line, pages_printed)
  739. FILE *summary ;
  740. int line, pages_printed ;
  741. {
  742.    char *s ;
  743.    int i ;
  744.    int max_descrip ;
  745.    int len ;
  746.  
  747.    s = buffer[line] ;
  748.    if (start_of_entry(s))
  749.       {
  750.       summary_line[3] = summary_line[0] = ' ' ;
  751.       summary_line[1] = s[4] ;     /* output interrupt number */
  752.       summary_line[2] = s[5] ;
  753.       summary_line[4] = '\0' ;
  754.       len = 4 ;
  755.       s = buffer[line+1] ;
  756.       while (*s && isspace(*s))
  757.      s++ ;
  758.       if (*s == 'A')
  759.      {
  760.      if (s[1] == 'X')
  761.         i = 4 ;
  762.      else
  763.         i = (s[1] == 'H') ? 2 : 0 ;
  764.      }
  765.       else
  766.      i = 0 ;
  767.       if (i)
  768.      {
  769.      while (*s && *s != '=')
  770.         s++ ;
  771.      s++ ;    /* skip the equal sign */
  772.      while (*s && isspace(*s))
  773.         s++ ;
  774.      if (isxdigit(*s) && isxdigit(s[1]))
  775.         {
  776.         summary_line[len++] = *s++ ;
  777.         summary_line[len++] = *s++ ;
  778.         summary_line[len++] = ' ' ;
  779.         if (i == 4)
  780.            {
  781.            summary_line[len++] = *s++ ;
  782.            summary_line[len++] = *s ;
  783.            }
  784.         else
  785.            {
  786.            summary_line[len++] = '-' ;
  787.            summary_line[len++] = '-' ;
  788.            }
  789.         summary_line[len++] = ' ' ;
  790.         }
  791.      else
  792.         {
  793.         /* wasn't legal digit, so no numbers */
  794.         strcpy(summary_line+len,"-- -- ") ;
  795.         len += 6 ;
  796.         }
  797.      }
  798.       else
  799.      {
  800.      strcpy(summary_line+len,"-- -- ") ;
  801.      len += 6 ;
  802.      }
  803.       if (page_numbers)
  804.      {
  805.      itoa(pages_printed,num,10) ;
  806.      for (i = strlen(num) ; i < 3 ; i++)
  807.         summary_line[len++] = ' ' ;
  808.      strcpy(summary_line+len,num) ;
  809.      len += strlen(num) ;
  810.      summary_line[len++] = ' ' ;
  811.      }
  812.       s = buffer[line] + 7 ;    /* find function description */
  813.       if (*s && *s != '-')    /* does the heading contain flags? */
  814.      {
  815.      while (*s && !isspace(*s))
  816.         summary_line[len++] = *s++ ;
  817.      summary_line[len++] = '>' ;
  818.      summary_line[len++] = ' ' ;
  819.      while (*s && *s != '-')
  820.         s++ ;
  821.      }
  822.       while (*s && !isspace(*s))
  823.      s++ ;
  824.       while (*s && isspace(*s))
  825.      s++ ;
  826.       max_descrip = (page_width > sizeof(summary_line)-1) ? 
  827.                    sizeof(summary_line)-1 : page_width ;
  828.       while (len < max_descrip && *s)
  829.      summary_line[len++] = *s++ ;
  830.       summary_line[len] = '\0' ;
  831.       if (do_summary && summary)
  832.      output_line(summary_line,summary) ;
  833.       }
  834. }
  835.  
  836. /***********************************************/
  837.  
  838. void start_format(line)
  839. char *line ;
  840. {
  841.    indent_line(formats) ;
  842.    (*printer->put_line)(formats,79) ;
  843.    fputc('\n',formats) ;
  844.    indent_line(formats) ;
  845.    fputs(summary_line,formats) ;
  846.    fputc('\n',formats) ;
  847.    indent_line(formats) ;
  848.    fputc('\t',formats) ;
  849.    fputs(line+10,formats) ;
  850.    fputc('\n',formats) ;
  851.    echo_format = TRUE ;
  852. }
  853.  
  854. /***********************************************/
  855.  
  856. void print_line(line)
  857. char *line ;
  858. {
  859.    if (*line)
  860.       {
  861.       if (divider_line(line))
  862.      {
  863.      indent_line(outfile) ;
  864.      (*printer->put_line)(outfile,79) ;
  865.      fputc('\n', outfile) ;
  866.      echo_format = FALSE ;
  867.      }
  868.       else
  869.      {
  870.      output_line(line, outfile) ;
  871.      if (echo_format)
  872.         output_line(line,formats) ;
  873.      }
  874.       }
  875.    else
  876.       {
  877.       fputc('\n', outfile) ;
  878.       echo_format = FALSE ;
  879.       }
  880. }
  881.  
  882. /***********************************************/
  883.  
  884. void make_description(desc,line)
  885. char *desc ;
  886. int line ;
  887. {
  888.    summarize(NULL,line,0) ;
  889.    memcpy(desc,"INT ", 4) ;
  890.    desc += 4 ;
  891.    *desc++ = summary_line[1] ;
  892.    *desc++ = summary_line[2] ;
  893.    if (summary_line[4] != '-')
  894.       {
  895.       memcpy(desc,", AH=", 5) ;
  896.       desc += 5 ;
  897.       *desc++ = summary_line[4] ;
  898.       *desc++ = summary_line[5] ;
  899.       if (summary_line[7] != '-')
  900.      {
  901.      memcpy(desc,", AL=", 5) ;
  902.      desc += 5 ;
  903.      *desc++ = summary_line[7] ;
  904.      *desc++ = summary_line[8] ;
  905.      }
  906.       }   
  907.    *desc = '\0' ;
  908. }
  909.  
  910. /***********************************************/
  911.  
  912. char *determine_heading(last)
  913. int last ;
  914. {
  915.    int i ;
  916.    char *heading ;
  917.    char num[10] ;
  918.    
  919.    if (start_of_entry(buffer[0]))
  920.       {
  921.       make_description(header_first.desc,0) ;
  922.       header_first.part = 1 ;
  923.       header_first.first_on_page = TRUE ;
  924.       }
  925.    else if (header_last.part == 0)  /* very first entry? */
  926.       {
  927.       for (i = 0 ; i < last ; i++)
  928.      if (start_of_entry(buffer[i]))
  929.         {
  930.         make_description(header_first.desc,i) ;
  931.         header_first.part = 1 ;
  932.         header_first.first_on_page = TRUE ;
  933.         break ;
  934.         }
  935.       }
  936.    else
  937.       {
  938.       strcpy(header_first.desc,header_last.desc) ;
  939.       header_first.part = header_last.part + 1 ;
  940.       header_first.first_on_page = FALSE ;
  941.       }
  942.    /* assume entry spans entire page */
  943.    strcpy(header_last.desc,header_first.desc) ;
  944.    header_last.part = header_first.part ;
  945.    header_last.first_on_page = header_first.first_on_page ;
  946.    /* find last entry on page */
  947.    if (header_first.part > 0)
  948.       {
  949.       if ((heading = calloc(1,MAXLINE)) == NULL)
  950.          return NULL ;
  951.       for (i = last-1 ; i > 0 ; i--)
  952.      if (start_of_entry(buffer[i]))
  953.         {
  954.         make_description(header_last.desc,i) ;
  955.         header_last.part = 1 ;
  956.         header_last.first_on_page = FALSE ;
  957.         break ;
  958.         }
  959.       strcpy(heading,header_first.desc) ;
  960.       if (header_first.part > 1)
  961.      {
  962.      strcat(heading," (Part ") ;
  963.      itoa(header_first.part,num,10) ;
  964.      strcat(heading,num) ;
  965.      strcat(heading,")") ;
  966.      }
  967.       if (strcmp(header_first.desc,header_last.desc) != 0 ||
  968.       header_first.part != header_last.part)
  969.      {
  970.      strcat(heading," to ") ;
  971.      strcat(heading,header_last.desc) ;
  972.      if (header_last.part > 1)
  973.         {
  974.         strcat(heading," (Part ") ;
  975.         itoa(header_last.part,num,10) ;
  976.         strcat(heading,num) ;
  977.         strcat(heading,")") ;
  978.         }
  979.      }
  980.       return heading ; 
  981.       }
  982.    else /* no headings yet */
  983.       return NULL ;
  984. }
  985.  
  986. /***********************************************/
  987.  
  988. void print_buffer(last,lines_per_page,total_lines,use_FF)
  989. int last, lines_per_page, total_lines ;
  990. int use_FF ;
  991. {
  992.    int i ;
  993.  
  994.    pages_printed++ ;
  995.    if (do_headers)
  996.       {
  997.       char *heading ;
  998.       
  999.       if ((heading = determine_heading(last)) != NULL)
  1000.      {
  1001.          indent_to(40-strlen(heading)/2,outfile) ;
  1002.      if (boldface)
  1003.         if (printer_bold)
  1004.            {
  1005.            fputcstr(&printer->bold_on,outfile) ;
  1006.            fputs(heading,outfile) ;
  1007.            fputcstr(&printer->bold_off,outfile) ;
  1008.            }
  1009.         else
  1010.            {
  1011.            fputs(heading,outfile) ;
  1012.            fputc('\r',outfile) ;
  1013.            indent_to(40-strlen(heading)/2,outfile) ;
  1014.            fputs(heading,outfile) ;
  1015.            }
  1016.      free(heading) ;
  1017.      }
  1018.       fputs("\n\n",outfile) ;
  1019.       }
  1020.    for (i = 0 ; i < last ; i++)
  1021.       {
  1022.       if (pages_printed >= first_page && pages_printed <= last_page)
  1023.      print_line(buffer[i]) ;
  1024.       if (do_summary || do_formats)  /* need summary lines if doing formats */
  1025.      summarize(summary,i,pages_printed) ;
  1026.       if (do_formats && strncmp(buffer[i],"Format of ",10) == 0)
  1027.      start_format(buffer[i]) ;
  1028.       }
  1029.    if (pages_printed >= first_page && pages_printed <= last_page)
  1030.       {
  1031.       if (page_numbers)
  1032.      {
  1033.      for (i = last ; i < lines_per_page - 1 ; i++)
  1034.         fputc('\n', outfile) ;
  1035.      indent_to(38,outfile) ;
  1036.      fputs("- ", outfile) ;
  1037.      itoa(pages_printed, num, 10) ;
  1038.      fputs(num, outfile) ;
  1039.      fputs(" -\n", outfile) ;
  1040.      }
  1041.       if (use_FF)
  1042.      fputc('\f', outfile) ;
  1043.       else
  1044.      for (i = page_numbers?lines_per_page:last ; i<total_lines ; i++)
  1045.         fputc('\n', outfile) ;
  1046.       if (duplex)
  1047.      {
  1048.      if ((pages_printed % 2) == 1)    /* next page even or odd? */
  1049.         fputcstr(&printer->marginl, outfile) ;    /* even page */
  1050.      else
  1051.         fputcstr(&printer->marginr, outfile) ;    /* odd page */
  1052.      }
  1053.       }
  1054. }
  1055.  
  1056. /***********************************************/
  1057.  
  1058. void display_printers()
  1059. {
  1060.    int i ;
  1061.    
  1062.    fputs("Valid printer names are:\n",stderr) ;
  1063.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  1064.       {
  1065.       fputc('\t',stderr) ;
  1066.       fputs(printers[i].name,stderr) ;
  1067.       fputc('\n',stderr) ;
  1068.       }
  1069.    fputs("When entering the printer name, use either a dash or an underscore\n",stderr) ;
  1070.    fputs("in place of blanks.  Case is ignored, and the name may be abbreviated\n",stderr) ;
  1071.    fputs("to the shortest unique prefix.\n",stderr) ;
  1072.    exit(1) ;
  1073. }
  1074.  
  1075. /***********************************************/
  1076.  
  1077. void select_printer(name)
  1078. char *name ;
  1079. {
  1080.    int i, len, prt = -1 ;
  1081.    
  1082.    len = strlen(name) ;
  1083.    for (i = 0 ; i < len ; i++)        /* convert dashes and underscores to blanks */
  1084.       if (name[i] == '-' || name[i] == '_')
  1085.      name[i] = ' ' ;
  1086.    for (i = 0 ; i < NUM_PRINTERS ; i++)
  1087.       if (strnicmp(name,printers[i].name,strlen(name)) == 0)
  1088.      if (prt == -1)
  1089.         prt = i ;
  1090.      else
  1091.         fatal("Ambiguous printer name!  Use -P? to list printers.") ;
  1092.    if (prt == -1)
  1093.       fatal("Unknown printer name!  Use -P? to list printers.") ;
  1094.    else
  1095.       printer = &printers[prt] ;
  1096. }
  1097.  
  1098. /***********************************************/
  1099.  
  1100. struct filter_list *add_filter_info(list,str)
  1101. struct filter_list *list ;
  1102. char *str ;
  1103. {
  1104.    struct filter_list *new ;
  1105.    
  1106.    if ((new = (struct filter_list *)calloc(1,sizeof(struct filter_list))) != NULL)
  1107.       {
  1108.       new->next = list ;
  1109.       new->str = strupr(strdup(str)) ;
  1110.       if (new->str == NULL)
  1111.      new = NULL ;
  1112.       }
  1113.    if (new == NULL)
  1114.       {
  1115.       fputs("Error: out of memory\n",stderr) ;
  1116.       exit(1) ;
  1117.       }
  1118.    return new ;
  1119. }
  1120.  
  1121. /***********************************************/
  1122.  
  1123. void build_filter_lists(file)
  1124. char *file ;
  1125. {
  1126.    FILE *fp ;
  1127.    char buf[MAXLINE] ;
  1128.    int len ;
  1129.    
  1130.    if ((fp = fopen(file,"r")) == NULL)
  1131.       {
  1132.       fputs("Warning: unable to open filtering file, will print entire list.\n",stderr) ;
  1133.       do_filter = FALSE ;
  1134.       }
  1135.    else /* OK, file is open, so start reading */
  1136.       {
  1137.       while (!feof(fp))
  1138.      {
  1139.      buf[0] = '\0' ;
  1140.      if (fgets(buf, sizeof(buf), fp) == NULL)
  1141.         {
  1142.         if (!feof(fp)) /* was it an error other than EOF? */
  1143.            fputs("Warning: error reading filtering data, filtering may be incomplete.\n",stderr) ;
  1144.         break ;
  1145.         }
  1146.      len = strlen(buf) ;
  1147.      if (len > 0 && buf[len-1] == '\n')
  1148.         buf[--len] = '\0' ;
  1149.      if (len > 1)
  1150.         {
  1151.         switch (buf[0])
  1152.            {
  1153.            case '+':
  1154.           includes = add_filter_info(includes,buf+1) ;
  1155.           break ;
  1156.            case '-':
  1157.           excludes = add_filter_info(excludes,buf+1) ;
  1158.           break ;
  1159.            case '#':        /* comment lines */
  1160.            default:
  1161.           break ;
  1162.            }
  1163.         }
  1164.      }
  1165.       fclose(fp) ;
  1166.       do_filter = TRUE ;
  1167.       }
  1168. }
  1169.  
  1170. /***********************************************/
  1171.  
  1172. int _Cdecl main(argc,argv)
  1173. int argc ;
  1174. char *argv[] ;
  1175. {
  1176.    int lines_per_page = -1 ;
  1177.    int total_lines = -1 ;
  1178.    int use_FF = TRUE ;
  1179.    int last_line ;
  1180.    int body_lines ;
  1181.    char *typeface = NULL ;
  1182.    char *summary_file = NULL ;
  1183.    char *formats_file = NULL ;
  1184.    char *filter_file = NULL ;
  1185.    char *last_page_num ;
  1186.    
  1187.    fputs("INTPRINT v", stderr) ;
  1188.    fputs(VERSION, stderr) ;
  1189.    fputs(" by Ralf Brown and others.  Donated to the Public Domain.\n",stderr) ;
  1190.    if (argc == 1 && isatty(0))
  1191.       usage() ;      /* give help if invoked with no args and keybd input */
  1192.    while (argc >= 2 && argv[1][0] == '-')
  1193.       {
  1194.       switch (argv[1][1])
  1195.      {
  1196.      case 'B':
  1197.         printer_bold = TRUE ;
  1198.         /* fall through to -b */
  1199.      case 'b':
  1200.         boldface = TRUE ;
  1201.         break ;
  1202.      case 'd':
  1203.         duplex = TRUE ;
  1204.         break ;
  1205.      case 'e':
  1206.         indent = 8 ;
  1207.         page_width = 87 ;  /* 96 - indent - 1 right margin */
  1208.         break ;
  1209.      case 'f':
  1210.         formats_file = argv[1]+2 ;
  1211.         break ;
  1212.      case 'F':
  1213.         filter_file = argv[1]+2 ;
  1214.         break ;
  1215.      case 'H':   /* page headers */
  1216.         do_headers = TRUE ;
  1217.         break ;
  1218.      case 'i':
  1219.         indent = atoi(argv[1]+2) ;
  1220.         break ;
  1221.      case 'I':
  1222.         IBM_chars = TRUE ;
  1223.         break ;
  1224.      case 'l':
  1225.         lines_per_page = atoi(argv[1]+2) ;
  1226.         break ;
  1227.      case 'L':
  1228.         total_lines = atoi(argv[1]+2) ;
  1229.         break ;
  1230.      case 'm':
  1231.         multi_file = TRUE ;
  1232.         break ;
  1233.      case 'n':
  1234.         pages_printed = atoi(argv[1]+2) ;
  1235.         break ;
  1236.      case 'P':
  1237.         if (argv[1][2] == '?')
  1238.            display_printers() ;
  1239.         else
  1240.            select_printer(argv[1]+2) ;
  1241.         break ;
  1242.      case 'p':
  1243.         page_numbers = TRUE ;
  1244.         break ;
  1245.      case 'r':
  1246.         first_page = atoi(argv[1]+2) ;
  1247.         last_page_num = strchr(argv[1]+2, ':') ;
  1248.         last_page = last_page_num ? atoi(last_page_num+1) : 0 ;
  1249.         if (last_page == 0)
  1250.            last_page = 9999 ;
  1251.         break ;
  1252.      case 's':
  1253.         summary_file = argv[1]+2 ;
  1254.         break ;
  1255.      case 't':
  1256.         typeface = argv[1]+2 ;
  1257.         break ;
  1258.      case 'w':
  1259.         widow_length = atoi(argv[1]+2) ;
  1260.         break ;
  1261.      default:
  1262.         usage() ;
  1263.      }
  1264.       argv++ ;
  1265.       argc-- ;
  1266.       }
  1267.    if (printer == NULL)
  1268.       select_printer("default") ;
  1269.    /* apply any necessary overrides to parameters */
  1270.    if (printer->indent != -1)
  1271.       indent = printer->indent ;
  1272.    if (lines_per_page <= 0)
  1273.       lines_per_page = printer->lines_per_page ;
  1274.    if (total_lines <= 0)
  1275.       total_lines = printer->page_length ;
  1276.    if (page_width <= 0)
  1277.       page_width = printer->page_width ;
  1278.    if (printer->flag)
  1279.       *(printer->flag) = TRUE ;
  1280.    if (cstrlen(&printer->bold_on) == 0)     /* control sequences for bold? */
  1281.       printer_bold = FALSE ;        /* if not, don't try to use them */
  1282.  
  1283.    /* open the summary file, if any */
  1284.    if (summary_file && *summary_file)
  1285.       if ((summary = fopen(summary_file, pages_printed ? "a":"w")) != NULL)
  1286.      do_summary = TRUE ;
  1287.       else
  1288.      fputs("unable to open summary file\n", stderr) ;
  1289.    /* open the data formats file, if any */
  1290.    if (formats_file && *formats_file)
  1291.       if ((formats = fopen(formats_file, pages_printed ? "a":"w")) != NULL)
  1292.      do_formats = TRUE ;
  1293.       else
  1294.      fputs("unable to open formats file\n", stderr) ;
  1295.    /* initialize filtering data, if specified */
  1296.    if (filter_file && *filter_file)
  1297.       build_filter_lists(filter_file) ;
  1298.    if (total_lines <= lines_per_page)
  1299.       {
  1300.       total_lines = lines_per_page ;
  1301.       use_FF = TRUE ;
  1302.       }
  1303.    else
  1304.       use_FF = FALSE ;
  1305.    if (argc == 2 || argc == 3)
  1306.       {
  1307.       input_file = argv[1] ;
  1308.       infile = fopen(input_file,"r") ;
  1309.       if (infile == NULL)
  1310.      fatal("unable to open input file") ;
  1311.       if (argc == 3)
  1312.      {
  1313.      outfile = fopen(argv[2],(pages_printed?"a":"w")) ;
  1314.      if (outfile == NULL)
  1315.         fatal("unable to open output file") ;
  1316.      }
  1317.       else
  1318.      outfile = stdout ;
  1319.       }
  1320.    else
  1321.       usage() ;
  1322.    if (lines_per_page < 20 || lines_per_page > MAXPAGE)
  1323.       {
  1324.       fputs("Surely you jest!  At least 20 and at most 200 lines per page.\n\n", stderr) ;
  1325.       usage() ;
  1326.       }
  1327.    if (widow_length < 3 || widow_length > lines_per_page / 2)
  1328.       {
  1329.       fputs("Widow lines (-w) must be set to at least 3 and at most one-half of the\n",stderr) ;
  1330.       fputs("page length.  Using default of 10 lines.\n",stderr) ;
  1331.       widow_length = 10 ;
  1332.       }
  1333. #ifdef __TURBOC__
  1334.    setvbuf(infile,NULL,_IOFBF,10240) ;    /* use larger disk buffers */
  1335.    setvbuf(outfile,NULL,_IOFBF,10240) ; /* for better performance */
  1336.    if (do_summary)
  1337.       setvbuf(summary,NULL,_IOFBF,4096) ;
  1338.    if (do_formats)
  1339.       setvbuf(formats,NULL,_IOFBF,4096) ;
  1340. #endif /* __TURBOC__ */
  1341.    /* set up the printer */
  1342.    fputcstr(&printer->init1,outfile) ;
  1343.    fputcstr(&printer->init2,outfile) ;
  1344.    if (HPPCL_mode)
  1345.       {
  1346.       fputs(HPPCL_FONT_ON_A,outfile) ;
  1347.       if (typeface)
  1348.      fputs(typeface,outfile) ;
  1349.       else
  1350.      fputs("8",outfile) ;
  1351.       fputs(HPPCL_FONT_ON_B,outfile) ;
  1352.       }
  1353.    if (duplex)
  1354.       {
  1355.       fputcstr(&printer->duplex_on,outfile) ;
  1356.       if ((pages_printed % 2) == 1)    /* next page odd or even? */
  1357.      fputcstr(&printer->marginl,outfile) ;    /* even */
  1358.       else
  1359.      fputcstr(&printer->marginr,outfile) ;    /* odd */
  1360.       }
  1361.    else
  1362.       fputcstr(&printer->marginc,outfile) ;    /* non-duplex, so center */
  1363.    /* start the summary file */
  1364.    if (do_summary && pages_printed == 0)
  1365.       {          /* create header, but only on first part */
  1366.       /* set up the printer */
  1367.       fputcstr(&printer->init1,summary) ;
  1368.       fputcstr(&printer->init2,summary) ;
  1369.       fputcstr(&printer->marginc,summary) ;
  1370.       indent_line(summary) ;
  1371.       fputs("\t\t\t\tInterrupt Summary\n",summary) ;
  1372.       indent_line(summary) ;
  1373.       fputs("\t\t\t\t", summary) ;
  1374.       (*printer->put_line)(summary,17) ;
  1375.       fputs("\n\n",summary) ;
  1376.       indent_line(summary) ;
  1377.       fputs("INT AH AL", summary) ;
  1378.       if (page_numbers)
  1379.      fputs(" Page", summary) ;
  1380.       fputs("\t\t\tDescription\n", summary) ;
  1381.       indent_line(summary) ;
  1382.       (*printer->put_line)(summary,page_width) ;
  1383.       fputc('\n', summary) ;
  1384.       }
  1385.    /* start the data formats file */
  1386.    if (do_formats && pages_printed == 0)
  1387.       {          /* create header, but only on first part */
  1388.       /* set up the printer */
  1389.       fputcstr(&printer->init1,formats) ;
  1390.       fputcstr(&printer->init2,formats) ;
  1391.       fputcstr(&printer->marginc,formats) ;
  1392.       indent_line(formats) ;
  1393.       fputs("\t\t\tData Structure Formats\n", formats) ;
  1394.       indent_line(formats) ;
  1395.       fputs("\t\t\t", formats) ;
  1396.       (*printer->put_line)(formats,22) ;
  1397.       fputs("\n\n", formats) ;
  1398.       indent_line(formats) ;
  1399.       fputs("INT AH AL", formats) ;
  1400.       if (page_numbers)
  1401.      fputs(" Page", formats) ;
  1402.       fputs("\t\tData Structure\n", formats) ;
  1403.       }
  1404.    if (page_numbers)
  1405.       body_lines = lines_per_page - 2 ;
  1406.    else
  1407.       body_lines = lines_per_page ;
  1408.    if (do_headers)
  1409.       body_lines -= 2 ;
  1410.    last_line = 0 ;
  1411.    while (!feof(infile) && !out_of_files)
  1412.       {
  1413.       fill_buffer(last_line,body_lines) ;
  1414.       last_line = find_page_break(body_lines) ;
  1415.       print_buffer(last_line,lines_per_page,total_lines,use_FF) ;
  1416.       }
  1417.    if (last_line < body_lines)
  1418.       {
  1419.       int i ;
  1420.       
  1421.       for (i = last_line ; i < body_lines ; i++)
  1422.      strcpy(buffer[i-last_line], buffer[i]) ;
  1423.       print_buffer(body_lines-last_line,lines_per_page,total_lines,use_FF) ;
  1424.       }
  1425.    /* reset the printer */
  1426.    fputcstr(&printer->term1,outfile) ;
  1427.    fputcstr(&printer->term2,outfile) ;
  1428.    fflush(outfile) ;
  1429.    itoa(pages_printed, num, 10) ;
  1430.    fputs(num, stderr) ;
  1431.    fputs(" pages\n", stderr) ;
  1432.    if (do_summary)
  1433.       {
  1434.       /* reset the printer */
  1435.       fputcstr(&printer->term1,summary) ;
  1436.       fputcstr(&printer->term2,summary) ;
  1437.       fclose(summary) ;
  1438.       }
  1439.    if (do_formats)
  1440.       {
  1441.       /* reset the printer */
  1442.       fputcstr(&printer->term1,formats) ;
  1443.       fputcstr(&printer->term2,formats) ;
  1444.       fclose(formats) ;
  1445.       }
  1446.    fclose(infile) ;
  1447.    return 0 ;
  1448. }
  1449.