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