home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / prog2 / cpr31.lzh / CPR.C next >
Encoding:
C/C++ Source or Header  |  1988-07-18  |  46.2 KB  |  1,321 lines

  1. /*
  2.     CPR.C            " Prints 'C' Files with Table of Contents "
  3.                      "             AND LOTS MORE               "
  4.  
  5.     Turbo C Version 1.0 or 1.5
  6.  
  7. Originally Written by :
  8.         Paul Breslin
  9.         Human Computing Resources Corp.
  10.         10 South Mary Street
  11.         Toronto, Ontario
  12.         Canada, M4Y 1P9
  13.  
  14. Modified by :
  15.         Lance E. Shepard        Rick Wise                Blake McBride
  16.         CCI & RIT                CALCULON Corp.            3900 SW 52nd Ave. #803
  17.         Rochester, NY            Rockville, MD 20850        Pembroke Park, FL 33023
  18.  
  19.         John Stidd                Dale Loftis
  20.         1570 Neston Way            3020 Yorba Linda #F-16
  21.         Los Altos, CA 94022        Fullerton, CA 92631
  22.  
  23. Special Notes:
  24.     A.)  Table of Contents is held in Local Data Segment
  25.            So Compile This Program as SMALL (at Minimum).
  26. */
  27. /* *************************************************************************
  28. **                        Program Revision History
  29. **
  30. **  By Dale Loftis
  31. **  10-3-87   Changed WIDTH to 132, Tabs are now every 4, modified so
  32. **             that temporary file is deleted if control - break is hit,
  33. **             Improved the clarity of the instructions if no parmeters
  34. **              are given.
  35. **
  36. **  10-17-87  Changed so that no blank lines are printed in between structures.
  37. **
  38. **  11-06-87  Added -@ RESPONSE FILE feature since you couldn't fit all the
  39. **             filenames onto the command line, upto 400 files can be printed.
  40. **
  41. **            Also adding the "Reading file # x of y" string and made program
  42. **             check the amount of free disk space before writing the files
  43. **             as the program would write the output file and run out of disk
  44. **             space and just put alot of junk on the disk.
  45. **
  46. **  11-08-87  Ver 1.0    Added -h HEADER FILE, -* "Print All 'C' Files,
  47. **                             -x Extra Lines and Program Version Number
  48. **
  49. **  01-10-88  Ver 1.1    Added call to setvbuf() to speed up file access.
  50. **
  51. **  01-25-88  Ver 1.2    Added -t  for option of just table of contents list
  52. **
  53. **  01-29-88  Ver 1.3    Fixed Bug.  funcname () would not be put in Table of
  54. **                         Contents because of space between funcname and ().
  55. **
  56. **  04-26-88  Ver 1.4    Added -p* option for starting page number and changed
  57. **                       Table of Contents so File Date and Time Shown.
  58. **
  59. **  05-12-88  Ver 3.0    Added -q* option to print files by section number
  60. **                       rather than by page number.
  61. **                       Added -t- option to suppress the Table of Contents
  62. **
  63. **  07-18-88  Ver 3.1    Fixed bug in printing by section where form feed was
  64. **                       not being output at the top of the file.
  65. */
  66. /* --------------------------------------------------------------------- */
  67. /*
  68.        Include Files for Library Function Prototypes
  69. */
  70. #include    <stdio.h>
  71. #include    <fcntl.h>
  72. #include    <alloc.h>
  73. #include    <dos.h>
  74. #include    <dir.h>
  75. #include    <conio.h>
  76. #include    <ctype.h>
  77. #include    <time.h>
  78. #include    <string.h>
  79. /* --------------------------------------------------------------------- */
  80. /*
  81.        Some Valuable Definitions
  82. */
  83. #define        O_RAW  O_BINARY                /* Handle File as Binary       */
  84.  
  85. #define        TEMPORARY_FILENAME    "CPR$.TMP"    /* temporary file name (always)*/
  86.  
  87. #define        MAJOR_VERSION    3            /* Current Software Version #   */
  88. #define        MINOR_VERSION    1
  89.  
  90. #define        BP                0x0C        /* Form feed                    */
  91. #define        COMPRESSED        0x0F        /* Compressed Print             */
  92. #define        MAX_S            256            /* Maximum string length        */
  93. #define        LENGTH            66            /* Default Page Length          */
  94. #define        WIDTH            132            /* Default page width           */
  95. #define        N_FILES            400            /* Maximum number of files      */
  96. #define        TOC_LEN            1024        /* Max Table of Contents entries*/
  97. #define        MAX_FNAME_SIZE    25            /* Max filename length in response file */
  98. #define        MAX_HDR_BYTES    500            /* Max bytes in header file     */
  99. #define        HEADER_SIZE        3            /* Header is 3 lines big        */
  100. /* -------------------------------------------------------------------------
  101. /* These Macros are used to determine valid characters for Table of Contents
  102. */
  103.  
  104. /* returns true if letter, digit, '_' or ' '*/
  105.  
  106. #define isidchr(c)      (isalnum(c) || (c == '_') || (c == ' '))
  107.  
  108. /* returns true if letter, digit, '_', '*', '\t' or '\n' */
  109.  
  110. #define isiechr(c)      (isidchr(c) || c=='*' || c=='\t' || c=='\n')
  111. /* --------------------------------------------------------------------- */
  112. /*
  113.        Internal Program Function Prototypes
  114. */
  115. int        c_break(void);        /* Called when BREAK is hit                  */
  116. int        file_stats(char *);    /* File Statistics function                  */
  117. char    *Rs();                /* Strips trailing blanks from string        */
  118. char    *EndComment();        /* Process string until end of comment       */
  119. char    *EndString();        /* Process string until end of quoted string */
  120. char    *expand();            /* Process string expanding TABS to Spaces   */
  121. char    *substr1();
  122. /* -------------------------------------------------------------------- */
  123. /*
  124.        Global Variables
  125. */
  126. FILE    *TempFile;                        /* Program Temporary File       */
  127. FILE    *File;                            /* Current File being worked on */
  128. FILE    *Rfile;                            /* Response File handle         */
  129. FILE    *Hfile;                            /* Header   File handle         */
  130.  
  131. struct ffblk fblock;            /* struct used for calculating file size */
  132. struct dfree disk_space;        /* struct used for finding free disk space */
  133.  
  134. char  file_time_buff[20];        /* file time is placed here      */
  135. char  file_date_buff[20];        /* file date is placed here      */
  136.  
  137. int        Braces;                    /* Keeps track of brace depth    */
  138. int        LineNumber;                /* Count output lines             */
  139. int        PageNumber = 1;            /* You figure this one out       */
  140. int        SectionNumber = 1;        /* and this one to               */
  141. int        PageLength = LENGTH;    /* Normal paper length           */
  142. int        PageWidth  = WIDTH;        /* normal page width             */
  143. int        OnePerPage = 0;            /* non-zero puts 1 function/page */
  144. int        NumLines   = 0;            /* non-zero puts line # in file  */
  145. int        Number     = 1;
  146. int        WantSorted = 1;            /* Sort the table of contents   */
  147. int        PageEnd;                /* Accounts for space at bottom */
  148. int        InComment;                /* Indicates if inside Comment  */
  149. int        InString;                /* Indicates if inside String   */
  150. int        double_strike;            /* # of times + 1 to write filename             */
  151. int        header_flag;            /* non-zero enables print codes/Dates/Page #'s  */
  152. int        header_lines;            /* number of extra lines from header file       */
  153. int        extra_lines;            /* non-zero enables extra lines after functions */
  154. int        table_contents;            /* non-zero indicates Table of Contents Only    */
  155. int        sectionflg;                /* non-zero indicates print by section          */
  156.  
  157. unsigned long    memfree;        /* amount of local memory left for file buffer  */
  158.  
  159. char    *TempName;                /* pointer to temporary filename   */
  160. char    *fname[N_FILES];        /* file names to be worked on      */
  161. char    *STDIN = "\n";          /* special string pointer value to */
  162.                                 /* flag a file as being stdin      */
  163. char    *Name;                    /* Current file name               */
  164. char    *ProgName;                /* This programs Path and Name     */
  165.  
  166. char    *Toc[TOC_LEN];            /* pointers to files in TOC        */
  167. int     TocPages[TOC_LEN];        /* page numbers                    */
  168. int     TocCount;                /* index into TOC arrays           */
  169.  
  170. char    header_buffer[MAX_HDR_BYTES];/* 500 byte buffer for user defined Page Headers */
  171. char    FunctionName[100];                /* Work area for parsing Func names */
  172. char    Todayv[45];                        /* Today's Time and Date         */
  173.  
  174. /* --------------------------------------------------------------------- */
  175. /*
  176.      The filenames[N_FILES][25] array allocates an array capable of holding
  177.     N_FILES filenames that are up to 25 characters long.
  178.  
  179.      Each filename in DOS can be 12 characters long and the response file
  180.     has a CRLF with each line and we also need a terminating zero byte
  181.     bringing the count up to 15. MAX_FNAME_SIZE bytes are provided for a
  182.     possible path
  183. */
  184. /* --------------------------------------------------------------------- */
  185. char filenames[N_FILES][MAX_FNAME_SIZE];    /* files read from response file */
  186.  
  187. /* --------------------------------------------------------------------- */
  188. /*
  189. **  The following string is the definition of tab stops.  Every 'T' is a
  190. **  tab, any other character is not.  It is currently defined as a tab
  191. **  every 4 spaces.  The comment below helps if you want to modify this,
  192. **  each row being 0+n, 50+n, 100+n, and 150+n, where n is the number
  193. **  above the declaration.  Don't try to number each row with a comment,
  194. **  because you'll notice that the '\'s make it one big string.
  195. */
  196. char   *TabDef = "\
  197. ---T---T---T---T---T---T---T---T---T---T---T---T--\
  198. -T---T---T---T---T---T---T---T---T---T---T---T--T-\
  199. ---T---T---T---T---T---T---T---T---T---T---T---T--\
  200. -T---T---T---T---T---T---T---T---T---T---T---T---T";
  201. /* ------------------------------------------------------------------------ */
  202. /*
  203. /*    Program Instructions (Note the %??? arguments)
  204. /*
  205. */
  206. char option_list[] = "\n\
  207. ----------------------------- VERSION %d.%d SWITCHES ------------------------\n\
  208.            -@*    Replace * with Response Filename (1 filename per line    )\n\
  209.            -a*    Replace * with Drive Wildcard\n\
  210.            -c     Printer Codes/Dates/Page #'s off (default is Enabled     )\n\
  211.            -d     Double Strike Printing Enabled   (default is Disabled    )\n\
  212.            -h*    Replace * with Header Filename\n\
  213.            -l##   Replace ## with PageLength       (default = %3d          )\n\
  214.            -n     Numbers Source Lines             (Resets to 1 w/each file)\n\
  215.            -o     Places 1 function on a Page      (default is multiple    )\n\
  216.            -p*    Replace * with starting Page Number\n\
  217.            -q*    Replace * with starting Section Number\n\
  218.            -s     Sort Table of Contents by Page # (default is Func. Name  )\n\
  219.            -t     Print Table of Contents Only     (-t- suppress's Table   )\n\
  220.            -w##   Replace ## with Width            (default = %3d          )\n\
  221.            -x     Enables Extra Lines after Functions (default is Disabled )\n\
  222.           [...]   Means multiple filenames may be listed\n\n\
  223.                Response Files should have 1 filename per line up to %d      \n\
  224.          characters followed by 1 CRLF and may contain up to %d filenames.  \n\n\
  225.                Header Files contain the Strings to Print at the top of      \n\
  226.          every page of the listing, entire file can be up to %d bytes.";
  227.  
  228. /* -------------------------------------------------------------------- */
  229. /*
  230.       It all Starts With MAIN
  231. */
  232. main(argc, argv)
  233. int argc;
  234. char    **argv;
  235. {
  236. unsigned long int total_disk_free = 0;
  237. unsigned char ch;
  238. register int    i;
  239. int nextf = 0;                      /* index into fname[]                */
  240. long    thetime;
  241.  
  242.     ctrlbrk(c_break);                /* set control-break handler         */
  243.     double_strike = 1;                /* default to no double strike       */
  244.     header_flag   = 1;                /* default to codes and headers      */
  245.     header_lines  = 0;                /* no extra lines from header file   */
  246.     extra_lines   = 0;                /* no extra lines after functions    */
  247.  
  248.     ProgName = argv[0];                /* grab pointer to the programs name */
  249.  
  250.     time(&thetime);                    /* grab the DOS time and date        */
  251.     strcpy(Todayv,ctime(&thetime));    /* convert to ascii (LF at END OF STRING) */
  252.     strtok(Todayv,"\n");            /* strip the annoying LF off         */
  253.  
  254.     if (argc == 1)                    /*if only the program name given     */
  255.         Usage();                    /* if no args, show instructions     */
  256.  
  257.     for (i = 1; i < argc; i++) {    /* other parse command line          */
  258.         if (argv[i][0] == '-')  {    /* check for switch flag "-"         */
  259.             switch (toupper(argv[i][1])) { /* and go thru the switches   */
  260.  
  261.             case '@':                    /* Response file */
  262.                 nextf = ReadResponseFile(argv[i]);
  263.             break;
  264.  
  265.             case 'A':                    /* "*.???" Print all specified files */
  266.                 nextf = StarDot(argv[i]);
  267.             break;
  268.  
  269.             case 'C':                    /* Print codes/Dates/Time and page # */
  270.                 header_flag = 0;
  271.             break;
  272.  
  273.             case 'D':                    /* Double Strike function names      */
  274.                 double_strike = 3;
  275.             break;
  276.  
  277.             case 'H':                    /* Header file                       */
  278.                 ReadHeaderFile(argv[i]);
  279.             break;
  280.  
  281.             case 'L':                    /* Number of lines per page          */
  282.                 if ( ! argv[i][2]) {    /* if -L ?? (ie.. a space)           */
  283.                     if (++i >= argc)    /* see if another argument           */
  284.                         Usage();        /* if no then print Help             */
  285.  
  286.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  287.                         Usage();                    /* No! Print Help        */
  288.  
  289.                     PageLength = atoi (argv[i]);    /* assign number         */
  290.                 }
  291.                 else {        /* Switch came as -L?? form (with no space)      */
  292.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  293.                         Usage();                    /* No! Print Help        */
  294.  
  295.                     PageLength = atoi(&argv[i][2]);    /* assign number         */
  296.                 }
  297.             break;
  298.  
  299.             case 'N':                    /* Number Source Lines               */
  300.                 NumLines = 1;
  301.             break;
  302.  
  303.             case 'O':                    /* 1 function per page               */
  304.                 OnePerPage = 1;
  305.             break;
  306.  
  307.             case 'P':                    /* Starting Page Number              */
  308.                 if ( ! argv[i][2]) {    /* if -P ?? (ie.. a space)           */
  309.                     if (++i >= argc)    /* see if another argument           */
  310.                         Usage();        /* if no then print Help             */
  311.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  312.                         Usage();                    /* No! Print Help        */
  313.                     PageNumber = atoi (argv[i]);    /* assign number         */
  314.                 }
  315.                 else {        /* Switch came as -P?? form (with no space)      */
  316.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  317.                         Usage();                    /* No! Print Help        */
  318.                     PageNumber = atoi(&argv[i][2]);    /* assign number         */
  319.                 }
  320.             break;
  321.  
  322.             case 'Q':                    /* Print by Section                  */
  323.                 if ( ! argv[i][2]) {    /* if -Q ?? (ie.. a space)           */
  324.                     if (++i >= argc)    /* see if another argument           */
  325.                         Usage();        /* if no then print Help             */
  326.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  327.                         Usage();                    /* No! Print Help        */
  328.                     SectionNumber = atoi (argv[i]);    /* assign number         */
  329.                 }
  330.                 else {        /* Switch came as -Q?? form (with no space)      */
  331.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  332.                         Usage();                    /* No! Print Help        */
  333.                     SectionNumber=atoi(&argv[i][2]);/* assign number         */
  334.                 }
  335.                 sectionflg = 1;
  336.             break;
  337.  
  338.             case 'S':                    /* Sorted Table of Contents          */
  339.                 WantSorted = 0;
  340.             break;
  341.  
  342.             case 'T':                    /* Print Table of Contents Only      */
  343.                 table_contents = 1;        /* enable flag                       */
  344.                 if( argv[i][2] == '-')    /* if disabling TOC                  */
  345.                     table_contents = -1;/* disable it                        */
  346.             break;
  347.  
  348.             case 'W':                    /* Page Width                        */
  349.                 if ( ! argv[i][2]) {    /* if -W ?? (ie.. a space)           */
  350.                     if (++i >= argc)    /* see if another argument           */
  351.                         Usage();        /* if no then print Help             */
  352.                     if ( ! isdigit (argv[i][0]))    /* is it a number?       */
  353.                         Usage();                    /* No! Print Help        */
  354.                     PageWidth = atoi (argv[i]);        /* assign number         */
  355.                 }
  356.                 else {        /* Switch came as -W?? form (with no space)      */
  357.                     if (!isdigit(argv[i][2]))        /* is it a number?       */
  358.                         Usage();                    /* No! Print Help        */
  359.                     PageWidth = atoi(&argv[i][2]);    /* assign number         */
  360.                 }
  361.             break;
  362.  
  363.             case 'X':                    /* Extra Lines after Functions       */
  364.                 extra_lines = 1;
  365.             break;
  366.  
  367.             case '\0':                    /* End of string?(out of enviroment) */
  368.                 if (nextf >= N_FILES) {
  369.                     fprintf (stderr, "%s: too many files\n", argv[0]);
  370.                     exit (1);
  371.                 }
  372.                 fname[nextf++] = STDIN;        /* any in excess goes to STDIN   */
  373.             break;
  374.  
  375.             default:                        /* No arguments given            */
  376.                 Usage();                    /* show program instructions     */
  377.             break;
  378.             }
  379.         }
  380.         else {        /* Argument (argv[i]) wasn't a switch parmeter           */
  381.             if (nextf >= N_FILES) {
  382.                 fprintf (stderr, "%s: too many files\n", argv[0]);
  383.                 exit (1);
  384.             }
  385.             fname[nextf++] = argv[i];    /* copy pointer to filename          */
  386.         }
  387.     }
  388.  
  389.     if ( ! nextf)                /* No files were specified                   */
  390.         fname[nextf++] = STDIN; /* so use STDIN as the input file            */
  391.  
  392.     PageEnd = PageLength - (1 + PageLength / 20);
  393.  
  394.     StartTempFile();                    /* open temporary file               */
  395.  
  396.     for (i = 0; i < nextf; i++) {        /* walk thru file list               */
  397.         if (fname[i] == STDIN) {        /* if no files                       */
  398.             File = stdin;                /* assign stdin as input             */
  399.             Name = "Standard Input";    /* assign name for printout          */
  400.             fprintf(stderr,"Accepting Input from STDIN, ^Z to END\n");
  401.         }
  402.         else  {                            /* there was a filename              */
  403.             if( (File = fopen( Name = fname[i], "r" )) == NULL )  {
  404.                 fprintf (stderr, "%s: Can't open file \"%s\"\n",
  405.                         ProgName, Name );
  406.                 continue;                /* keep going if not found           */
  407.             }
  408.             else {                        /* file opened OK so read            */
  409.                 fprintf(stderr, "\nReading File #%3d of %3d: \" %s \"",
  410.                         i+1, nextf, fname[i]);
  411.  
  412.                 memfree = coreleft();        /* compute amount of free memory */
  413.                 memfree = ( (memfree > 32767L) ?/* if to much memory then    */
  414.                                    32767L  :    /* set max for setvbuf       */
  415.                                    memfree );    /* else take as much as u can*/
  416.  
  417.                 if( setvbuf(File, NULL, _IOFBF, (int) memfree) != 0) {
  418.                     fprintf(stderr,"Input Buffer failed to allocate.\n");
  419.                 }
  420.             }
  421.         }
  422.         List();                    /* Read File in and process data             */
  423.  
  424.         if (File != stdin) {    /* if it's not STDIN                         */
  425.             fclose(File);        /* close file & deallocate buffer            */
  426.         }
  427.     }
  428.  
  429.     if( PageNumber > 1 || LineNumber > 0 )
  430.         BreakPage();
  431.  
  432.     EndTempFile();                /* Close Temporary File                     */
  433.  
  434.     fprintf(stderr,"\n\n");
  435.  
  436.     getdfree(0, &disk_space);/* find out free disk space after cpr$.tmp created */
  437.  
  438.     total_disk_free =    ( ( (long)disk_space.df_bsec   *    /* bytes per sector    */
  439.                             (long)disk_space.df_sclus) *    /* sectors per cluster */
  440.                             (long)disk_space.df_avail);        /* clusters available  */
  441.  
  442.     findfirst(TEMPORARY_FILENAME,&fblock,0);    /* read temp file size in    */
  443.  
  444.     if(fblock.ff_fsize >= total_disk_free) {    /* see if copy can be output */
  445.         fprintf(stderr,"Insufficient Disk Space!\n\
  446.                         \nMinimum of %lu bytes needed.\
  447.                         \n%lu bytes are available\n\
  448.                         \nDo You wish to continue? (Y/N)",
  449.                         fblock.ff_fsize, total_disk_free);
  450.         do {
  451.             ch = (toupper(getche()) );
  452.         }
  453.         while((ch != 'Y') && (ch != 'N'));
  454.  
  455.         if(ch != 'Y')
  456.             Done();                    /* Delete Temporary File             */
  457.  
  458.         fprintf(stderr,"\n\n");
  459.     }
  460.  
  461.     if((!table_contents) ||            /* if TOC and file enabled           */
  462.         (table_contents == 1))        /* or TOC only     enabled           */
  463.         DumpTableOfContents();        /* Print Table of Contents           */
  464.  
  465.     if((!table_contents) ||            /* if TOC and file enabled           */
  466.         (table_contents == -1))        /* or no TOC                         */
  467.         DumpTempFile();                /* then dump the file                */
  468.  
  469.     Done();                            /* Clean things up and leave         */
  470. }
  471. /*****************************************************************************/
  472. Usage()
  473. {
  474.         fprintf (stderr,"Usage: %s SWITCHES filename [...]",ProgName);
  475.         fprintf (stderr,option_list ,
  476.                    MAJOR_VERSION, MINOR_VERSION, LENGTH, WIDTH,
  477.                    MAX_FNAME_SIZE-1, N_FILES, MAX_HDR_BYTES);
  478.         exit(1);
  479. }
  480. /*****************************************************************************/
  481. StartTempFile()
  482. {
  483.     TempName = TEMPORARY_FILENAME;            /* Temporary Filename */
  484.  
  485.     if( (TempFile = fopen(TempName, "w")) == NULL ) {
  486.         fprintf (stderr, "%s: Can't open temp file!\n", ProgName);
  487.         exit(1);
  488.     }
  489. }
  490. /*****************************************************************************/
  491. EndTempFile()
  492. {
  493.     fclose (TempFile);
  494. }
  495. /*****************************************************************************/
  496. DumpTempFile()
  497. {
  498. int     fd,n;
  499. char    buff[1025];
  500.  
  501.     if ((fd = open (TempName, O_RDONLY | O_RAW)) == -1) {
  502.         fprintf (stderr, "%s: can't open temp file\n", ProgName);
  503.         exit (1);
  504.     }
  505.  
  506.     while ((n = read (fd, buff, 1024)) != 0) {
  507.         if (write (1, buff, n) == -1) {
  508.             fprintf (stderr, "%s: write error (1)\n", ProgName);
  509.             exit (1);
  510.         }
  511.     }
  512. }
  513. /*****************************************************************************/
  514. Done()
  515. {
  516.     if( TempName )            /* if you created a file  */
  517.         unlink( TempName );    /* Delete temporary file  */
  518.     exit(0);                /* and leave the hard way */
  519. }
  520. /*****************************************************************************/
  521. List()            /* Process Incoming File */
  522. {
  523. register int    bp;
  524. char            buffer[257];
  525.  
  526.     if( sectionflg ) {                            /* if by section             */
  527.         PageNumber = 1;                            /* Pages start at 1          */
  528.         LineNumber = 0;                            /* Lines reset each time     */
  529.  
  530.         BreakPage();                            /* form feed if allowed      */
  531.     }
  532.  
  533.     NewPage();                                    /* bump page & output header */
  534.     NewFile();
  535.  
  536.     bp = Braces = 0;                            /* no begin page and braces  */
  537.  
  538.     while( fgets(buffer, 256, File) != NULL ) {    /* read a line upto 256 bytes*/
  539.         Rs(buffer);                                /* Remove Trailing Spaces    */
  540.  
  541.         if( bp )                                /* if beginning page         */
  542.             NewFunction();                        /* setup for new function    */
  543.  
  544.         if( (LineNumber + 1) > PageEnd )         /* if going past page end   */
  545.             NewPage();                             /* start a new page         */
  546.  
  547.         if(!Braces && LooksLikeFunction(buffer)) /* no braces and a function */
  548.             AddToTableOfContents();                 /* then add to TOC          */
  549.  
  550.         bp = PutLine(buffer);
  551.         LineNumber++;
  552.     }
  553.     if( sectionflg )                             /* if by sections           */
  554.         SectionNumber ++;                         /* Bump to next Section     */
  555. }
  556. /*****************************************************************************/
  557. NewPage()                        /* Process New Page                          */
  558. {
  559.     if( LineNumber > HEADER_SIZE )  {
  560.         if( PageNumber >= 0 ) {
  561.             PageNumber ++;        /* bump Page Number      */
  562.         }
  563.         BreakPage();            /* form feed if allowed  */
  564.         LineNumber = 0;            /* set flag for a header */
  565.     }
  566.     if( LineNumber == 0 )        /* Each new page         */
  567.         PutHeader();            /* Outputs a Header      */
  568. }
  569. /*****************************************************************************/
  570. NewFile()
  571. {
  572. register int    i, l;
  573. char            temp[80];
  574.  
  575.     if (TocCount >= TOC_LEN) {
  576.         fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
  577.         exit (1);
  578.     }
  579.  
  580.     if( (Toc[TocCount] = (char *) malloc(130)) == NULL)    /* allocate some memory */
  581.         ReportMemoryError();
  582.  
  583.     sprintf (Toc[TocCount], "\n\tFile: %s ", Name);    /* to put filename into */
  584.     l = strlen(Toc[TocCount]) - 1;                    /* and findout how long it is */
  585.  
  586.     if( l < 64 )  {                                    /* if not to long */
  587.         i = (64 - l) / 8;                            /* calc. TAB increment */
  588.         for( l=0; l < i; ++l )                        /* keep within 64 columns */
  589.             strcat(Toc[TocCount],"\t");                /* and put some TAB's out */
  590.     }
  591.  
  592.     file_stats(Name);                                /* findout file stats  */
  593.  
  594.     if(! sectionflg ) {
  595.         sprintf (temp, "  Page %4d  (%s  %s)\n",    /* Page #, Time & date */
  596.             PageNumber, file_date_buff, file_time_buff);
  597.     }
  598.     else {
  599.         sprintf (temp, "  Section %4d (%s  %s)\n",    /* Section, Time & Date*/
  600.             SectionNumber, file_date_buff, file_time_buff);
  601.     }
  602.  
  603.     strcat(Toc[TocCount], temp);                    /* copy to main buffer */
  604.     ++ TocCount;                                    /* bump the entries    */
  605.  
  606.     if (NumLines)                                    /* if numbering lines  */
  607.         Number  = 1;                                /* reset linenumber    */
  608.  
  609.     InComment = InString = 0;                    /* not in comment or string */
  610. }
  611. /****************************************************************************/
  612. PutLine(l)
  613. register char   *l;
  614. {
  615. register char   c;
  616. int             bp;
  617. char            *save;
  618. char            *section, *p;
  619. int             offset;
  620. char            Digits[15];
  621. int             Size;
  622. int             pos;
  623.  
  624.     bp = 0;
  625.     for( save = expand(l);
  626.         ( (c = *l) != 0);
  627.                 ++l )    {                /* bump thru the string */
  628.  
  629.         if( InComment )                    /* if your in a comment  */
  630.             l = EndComment(l);            /* process till your out */
  631.         else
  632.         if( InString )                    /* if your in a string   */
  633.             l = EndString(l);            /* process till your out */
  634.         else
  635.         switch(c)  {                    /* it must be something  */
  636.             case '{':                    /* curly brace IN        */
  637.                 ++Braces;                /* increment brace count */
  638.             break;
  639.  
  640.             case '}':                    /* curly brace OUT       */
  641.                 if( --Braces == 0)        /* coming out yet?       */
  642.                     if (*(l+1) == ';')    /* is it structure?      */
  643.                         ++l;            /* continue thru string  */
  644.                     else
  645.                     if(extra_lines)         /* if option enabled    */
  646.                         bp = 1;             /* flag for extra lines */
  647.             break;
  648.  
  649.             case '\'':                    /* Forward Slash         */
  650.                 ++l;                    /* continue thru string  */
  651.             break;
  652.  
  653.             case '"':                    /* Quotation Mark        */
  654.                 InString = 1;            /* must be in a string   */
  655.             break;
  656.  
  657.             case '/':                    /* Start of Comment      */
  658.                 if( *(l+1) == '*' ) {    /* is next character * ? */
  659.                     InComment = 1;        /* must be in a comment  */
  660.                     ++l;                /* continue thru string  */
  661.                 }
  662.             break;
  663.         }
  664.     }
  665.  
  666.     if (NumLines)  {                    /* if line numbering enabled */
  667.         sprintf (Digits,"[%d]  ", Number);    /* make a string         */
  668.         Size = strlen(Digits);                /* calc. its size        */
  669.     }
  670.     else {
  671.         Size = 0;                        /* else it's size is 0       */
  672.     }
  673.  
  674.     if (strlen(save) +                    /* if original strings size  */
  675.                Size  >                    /* and the size of numbers   */
  676.                PageWidth)  {            /* are bigger than the width */
  677.         section = substr1(save, 0, PageWidth - Size);
  678.  
  679.         if (section[strlen(section) - 1] != ' ')
  680.             if (NULL == (p = strrchr(section, ' ')))
  681.                 offset = strlen(section);
  682.             else
  683.                 offset = p - section;
  684.             else
  685.                 offset = strlen(section) - 1;
  686.  
  687.         section[offset] = NULL;
  688.  
  689.         if (NumLines)  {    /* if line numbering is enabled */
  690.             fprintf (TempFile, "[%d]  %s\n", Number++, section);
  691.         }
  692.         else  {
  693.             fprintf (TempFile, "%s\n", section);
  694.         }
  695.  
  696.         pos = offset + 1;
  697.         do  {
  698.             section = substr1(save, pos, pos + PageWidth - 8);
  699.             if (strlen(save) - pos + 8 > PageWidth)
  700.                 if (section[strlen(section) - 1] != ' ')
  701.                     if (NULL == (p = strrchr(section, ' ')))
  702.                         offset = strlen(section);
  703.                     else
  704.                         offset = p - section;
  705.                     else
  706.                         offset = strlen (section) - 1;
  707.                     else
  708.                         offset = strlen(section);
  709.  
  710.                 section[offset] = NULL;
  711.  
  712. /** ----------------------------------------------------------------- **/
  713. /* Removed this for some reason
  714. /*
  715. /*                if (section[strlen(section) - 1] == '\n')
  716. /*                    section[strlen(section) - 1] = NULL;
  717. */
  718.  
  719. /*  Line is to long for pagewidth so continue on next line */
  720.  
  721.                 fprintf (TempFile, "C       %s\n", section);
  722.                     if (++LineNumber > PageEnd)
  723.                         NewPage();
  724.             }
  725.             while ((pos += offset + 1) < strlen(save));
  726.         }
  727.         else  {
  728.             if (NumLines)        /* if line numbering enabled */
  729.                 fprintf (TempFile, "[%d]  %s\n", Number++, save);
  730.             else
  731.                 fprintf (TempFile, "%s\n", save);
  732.         }
  733.     return(bp);
  734. }
  735. /*****************************************************************************/
  736. NewFunction()                    /* Process New Function                     */
  737. {
  738. register int    i;
  739.  
  740.     if( LineNumber > (PageLength * 3 / 4) )       /*  49.5 lines            */
  741.         NewPage();
  742.     else  {
  743.         if (!OnePerPage)  {                    /* if mult. functions per page  */
  744.             for( i=0; i < (PageLength/7); ++i )
  745.                 putc ('\n', TempFile);        /* add extra lines              */
  746.                 LineNumber += PageLength/7; /* set line counter also        */
  747.             }
  748.             else
  749.                 NewPage();                    /* otherwise its 1 func. per page*/
  750.     }
  751. }
  752. /*****************************************************************************/
  753. BreakPage()                        /* Process Page Break                        */
  754. {
  755.     if(header_flag)                /* if its allowed send a FORM FEED           */
  756.         putc (BP, TempFile);
  757. }
  758. /*****************************************************************************/
  759. PutHeader()
  760. {
  761. register int    i, l, j;
  762.  
  763.     if(header_flag)             /* if its allowed send a COMPRESSED Code */
  764.         putc (COMPRESSED, TempFile);
  765.  
  766.     putc ('\n', TempFile);
  767.  
  768.     if(header_flag ) {            /* if its allowed send out the HEADER */
  769.  
  770.         l = strlen(Name);        /* Filename or Table of Contents label length */
  771.  
  772.         for( j=0; j < double_strike; ++j) {
  773.             fprintf (TempFile, "%s", Name);    /* Write out Filename or TOC */
  774.             if( (j < 2) && (double_strike == 3) )
  775.                 putc('\r', TempFile);        /* Provide for Double Strike CR */
  776.         }
  777.         if( PageNumber > 0 ) {                /* if your not on the TOC pages */
  778.             for( i = (l+7)/8; i < 6; ++i )
  779.                 putc ('\t', TempFile);        /* Tab out for position         */
  780.  
  781.             if(! sectionflg ) {
  782.                 fprintf (TempFile, "%s\tPage: %d\n\n\n", Todayv,PageNumber);
  783.             }
  784.             else {
  785.                 fprintf (TempFile, "%s\tSection %3d - %d\n\n\n",
  786.                     Todayv,SectionNumber,PageNumber);
  787.             }
  788.  
  789.             if(header_lines)                        /* Header for TOP OF PAGE */
  790.                 fprintf (TempFile, "%s", header_buffer);
  791.         }
  792.         else {    /* 1st line of Table of Contents page gets the time and date */
  793.  
  794.             for( i = (l+7)/8; i < 6; ++i )            /* Tab out for time/date  */
  795.                 putc ('\t', TempFile);
  796.  
  797.             fprintf (TempFile, "%s\n\n", Todayv);        /* Todays Time and Date   */
  798.  
  799.             if(header_lines)                        /* Header for TOP OF PAGE */
  800.                 fprintf (TempFile, "%s", header_buffer);
  801.         }
  802.     }
  803.     LineNumber += (HEADER_SIZE + header_lines);        /* bump line number counter */
  804. }
  805. /*****************************************************************************/
  806. LooksLikeFunction(s)
  807. register char   *s;
  808. {
  809. register char   *p;
  810. char            *save;
  811. int             Cnt, nosl,nolp,norp,flg;
  812. char            Digits[15];
  813. int             AddOne = 0;
  814.  
  815.     if( InComment || InString)        /* if your in a comment or in a string */
  816.         return(0);                    /* just leave and return 0             */
  817.  
  818.     p = FunctionName;                /* assign pointer to function name string */
  819.     save = s;                        /* save address of string                 */
  820.  
  821.     nosl = nolp = norp = 0;            /* no left or right paren or no slash     */
  822.  
  823.     flg = 1;
  824.  
  825.     for(; *s && flg  ; s++)  {        /* go until end of string or flag is set  */
  826.         switch  (*s)  {                /* switch on each character in string     */
  827.             case  '(':                /* is it a left paren?                    */
  828.                 if (!nolp) {        /* if no left paren already               */
  829.                     nolp = 1;        /* flag that you've got one               */
  830.  
  831. /* 3/4/87 added following line to include ARGS in TOC */
  832.  
  833.                     *p++ = *s;        /* move byte of ARG into function buffer */
  834.                 }
  835.                 else
  836.                     return(0);        /* or return if you've already had one    */
  837.             break;
  838.  
  839.             case  ')':                /* is it a right paren?                   */
  840.                 if (nolp && !norp) {/* if already a left paren and no right yet */
  841.                     norp = 1;        /* flag that you've got a right paren     */
  842.  
  843. /* 3/4/87 added following line to include ARGS in TOC */
  844.                     *p++ = *s;        /* move byte of ARG into function buffer  */
  845.                 }
  846.                 else
  847.                     return(0);        /* or return if conditions were'nt right  */
  848.             break;
  849.  
  850.             default:                /* everything comes thru here             */
  851.                 if (!nolp)  {        /* if no left paren yet                   */
  852.                     if (isiechr(*s))  {    /* is it alpha,digit,'_*\t\n'?        */
  853.                         if (isidchr(*s))/* is it alpha,digit,'_' or ' '?      */
  854.                             *p++ = *s;    /* if it is store the byte for TOC    */
  855.                         else
  856.                             p = FunctionName;    /* start over if '*\t\n' & nolp */
  857.                     break;
  858.                     }
  859.                     else
  860.                         return(0);    /* return if conditions weren't right     */
  861.                 }
  862.  
  863.                 if (!norp)  {        /* if no right paren yet                  */
  864.                     if (isiechr(*s) || *s == ',') { /* is it alpha,digit,'_ *\t\n'?*/
  865.  
  866. /* 3/4/87 added following line to include ARGS in TOC */
  867.                         *p++ = *s;    /* move byte of ARG in function buffer    */
  868.                         break;
  869.                     }
  870.                     else
  871.                         return(0);        /* return if conditions weren't right */
  872.                 }
  873.  
  874.                 if (Cmemb(*s," \t\n\r") && !nosl)    /* is it ' \t\n\r' or no slash yet */
  875.                     break;
  876.  
  877.                 if (*s == '/' && !nosl)  {    /* is it a '/' and no slash yet   */
  878.                     nosl = 1;                /* flag that you've got one       */
  879.                     break;
  880.                 }
  881.  
  882.                 if (*s == '*' && nosl)  {    /* if its '*' & you got a slash already */
  883.                     flg = 0;                /* set flag to abort loop         */
  884.                     break;
  885.                 }
  886.                 return(0);                    /* return if conditions not right */
  887.         } /* end of switch */
  888.     }        /* end of for loop */
  889.  
  890.     if (nolp != 1)                            /* return if no left paren found  */
  891.         return(0);
  892.  
  893.     *p = '\0';                                /* else terminate function buffer */
  894.  
  895.     if (NumLines)  {                        /* if line numbering enabled      */
  896.         sprintf (Digits,"[%d]  ", Number);    /* format number into string      */
  897.         Cnt = strlen(Digits) + AddOne;
  898.         while (Cnt-- > 0)
  899.             putc (' ', TempFile);
  900.         AddOne = 0;
  901.     }
  902. /*
  903.  * This will cause the function name part of the line to
  904.  * be double striken.
  905. */
  906.     if( double_strike == 3) {
  907.         while (*save && *save != '(')        /* double strike up to func  name */
  908.             putc (*save++, TempFile);
  909.         putc ('\r', TempFile);                /* use CR for doublestrike        */
  910.     }
  911.     return(1);
  912. }
  913. /****************************************************************************/
  914. AddToTableOfContents()
  915. {
  916. register int    l;
  917. register char   *p;
  918.  
  919.     if (TocCount >= TOC_LEN) {
  920.         fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
  921.         exit (1);
  922.     }
  923.     l = strlen(FunctionName);                    /* find how long name is */
  924.     p = Toc[TocCount] = (char *) malloc(l+1);    /* allocate just enough memory */
  925.  
  926.     if( p == NULL)                                /* did it really allocate     */
  927.         ReportMemoryError();                    /* No! then report error      */
  928.  
  929.     strcpy(p, FunctionName);                    /* copy the name to new space */
  930.     TocPages[TocCount] = PageNumber;            /* plug the page number in    */
  931.     ++TocCount;                                    /* bump the count             */
  932. }
  933. /****************************************************************************/
  934. DumpTableOfContents()
  935. {
  936. register int    i, j, l;
  937.  
  938.     if( TocCount == 0 )        /* if there nothing to print */
  939.         return;                /* then just return          */
  940.  
  941.     if (WantSorted)            /* if you wanted it sorted by page number */
  942.         SortTableOfContents();    /* then we must sort it first         */
  943.  
  944.     Name = "Table of Contents";    /* give me a title for the page       */
  945.  
  946.     PageNumber = -1;            /* Table of Contents pages are not numbered */
  947.     LineNumber = 0;                /* and neither are the lines          */
  948.     TempFile = stdout;            /* default output to standard out     */
  949.  
  950.     NewPage();                    /* start out creating a new page      */
  951.  
  952.     for( i=0; i < TocCount; ++i ) {
  953.         if( Toc[i][0] == '\n' ) {
  954.             if( (LineNumber + 5) > PageEnd )
  955.                 NewPage();
  956.             printf("%s", Toc[i]);
  957.             LineNumber += 2;
  958.             continue;
  959.         }
  960.  
  961.         if( ++LineNumber > PageEnd )/* if going off end of page           */
  962.             NewPage();                /* start a new page                   */
  963.  
  964.         printf("\t\t%s ", Toc[i]);    /* print func. name in TOC            */
  965.         l = strlen(Toc[i]);            /* length if function name with parms */
  966.  
  967.         for( j=l; j < 48; ++j )        /* put dots out to column 48          */
  968.             putchar('.');            /* put dots out to page num. in TOC   */
  969.  
  970.             printf(" %d\n", TocPages[i]);    /* print page number for function */
  971.     }
  972.  
  973.     if( ! sectionflg ) {            /* if not printing by sections        */
  974.         if(header_flag)                /* if control codes are allowed       */
  975.             putchar(BP);            /* print a Form Feed                  */
  976.         else
  977.             putchar('\n');            /* otherwise its a New Line           */
  978.     }
  979.     fflush(stdout);                    /* make sure everything is written out*/
  980. }
  981. /****************************************************************************/
  982. /*
  983.        Sort Table of Contents by Page number rather than function name
  984. */
  985. SortTableOfContents()
  986. {
  987. register int    i, tempint;
  988. char            *tempchar;
  989. int                flag;
  990.  
  991.     do {
  992.         flag = 0;                /* default to already sorted */
  993.  
  994.         for (i = 0; i < TocCount - 1; i++) {    /* look at them all */
  995.             if (Toc[i][0] == '\n' || Toc[i+1][0] == '\n')
  996.                 continue;       /* don't sort across file names */
  997.  
  998.             if (strcmp (Toc[i], Toc[i+1]) > 0) {/* compare the strings        */
  999.                 tempchar = Toc[i];                /* copy to temp pointer       */
  1000.                 Toc[i] = Toc[i+1];                /* swap the pointers in array */
  1001.                 Toc[i+1] = tempchar;            /* put the temp pointer back  */
  1002.                 tempint = TocPages[i];            /* grab the page number       */
  1003.                 TocPages[i] = TocPages[i+1];    /* swap page numbers          */
  1004.                 TocPages[i+1] = tempint;        /* put the temp page number back */
  1005.                 flag = 1;                        /* indicate you've swapped    */
  1006.             }
  1007.         }
  1008.     }
  1009.     while (flag);            /* go until no more swaps can be made */
  1010. }
  1011. /****************************************************************************/
  1012. char *EndComment(p)            /* Process string until you come out of COMMENT */
  1013. register char   *p;
  1014. {
  1015. register char   c;
  1016.  
  1017.     while( (c = *p++) != 0 )            /* while there are chars to look at */
  1018.         if( c == '*' && *p == '/' ) {    /* and there a splat or a slash     */
  1019.             InComment = 0;                /* say your not in the comment      */
  1020.             break;                        /* and leave the loop               */
  1021.         }
  1022.     return(p-1);                        /* returning the new pointer addr.  */
  1023. }
  1024. /*****************************************************************************/
  1025. char *EndString(p)            /* Process string until you come out of STRING  */
  1026. register char   *p;
  1027. {
  1028. register char   c;
  1029.  
  1030.     while( (c = *p++) != 0 )            /* while there are chars to look at */
  1031.         if( c == '\\' ) {                /* and forward slashs for next line */
  1032.             continue;                    /* means "Just read on McDuck"      */
  1033.         }
  1034.         else if( c == '"' ) {            /* if you found the ending quote    */
  1035.             InString = 0;                /* say your not in a string anymore */
  1036.             break;                        /* and leave the loop               */
  1037.         }
  1038.     return(p-1);                        /* returning the new pointer addr.  */
  1039. }
  1040. /****************************************************************************/
  1041. /*
  1042.  *      This is the function substr1().  The calling sequence is:
  1043.  *
  1044.  *                      substr1(string, startpos, endpos).
  1045.  *
  1046.  *      The function returns a pointer to a static string (written over -
  1047.  *      on subsequent calls) which is a substring of the string `string'
  1048.  *      starting at `startpos' (the first position is 0 (zero)) and ending
  1049.  *      at `endpos' (non-inclusive).  All arguments must be present or
  1050.  *      strange things happen with the system stack.
  1051.  *
  1052.  *      An example of the use is:
  1053.  *
  1054.  *              x = substr1(string, 2, 5);
  1055.  *              (where string == "This is a test.")
  1056.  *
  1057.  *      This call returns a pointer to:
  1058.  *              "is "
  1059.  *      An error code of -1 is returned is the `endpos' is greater than
  1060.  *      `startpos'
  1061.  *
  1062.  *                                              Lance E. Shepard
  1063.  */
  1064. char *substr1(string, start, end)
  1065. char    *string;
  1066. int     start;
  1067. int     end;
  1068. {
  1069. static char  retstr[MAX_S];
  1070. int loop1;
  1071. int loop2;
  1072.  
  1073.     if (end < start)  {
  1074.         exit(-1);
  1075.     }
  1076.  
  1077.     for (loop2 = 0; loop2 < MAX_S; loop2++)
  1078.         retstr[loop2] = NULL;
  1079.  
  1080.     for (loop1 = start, loop2 = 0; string[loop1] != NULL &&
  1081.          loop1 < end && loop2 <= MAX_S; loop1++, loop2++)
  1082.             retstr[loop2] = string[loop1];
  1083.  
  1084.     retstr[++loop2] = NULL;
  1085.     return(retstr);
  1086. }
  1087. /****************************************************************************/
  1088. /*
  1089.  *      This is the function `char *expand().'  This function takes as
  1090.  *      an argument a NULL terminated string and replaces all occurances
  1091.  *      of the tab character with 8 (eight) spaces.  The function returns
  1092.  *      a pointer to a static string which is overwritten on subsequent
  1093.  *      calls.
  1094. */
  1095. /****************************************************************************/
  1096. char *expand(string)
  1097. char *string;
  1098. {
  1099. int count;
  1100. static char retstr[MAX_S];
  1101.  
  1102.     for (count = 0; count < MAX_S; retstr[count++] = NULL)
  1103.         ;
  1104.  
  1105.     for (count = 0; *string != NULL; count++, string++)  {
  1106.         if (*string == '\t')  {
  1107.             retstr[count] = ' ';
  1108. /*             while (((count + 1) % 8) != 0)     */
  1109.                 while (TabDef[count] != 'T')
  1110.                     retstr[++count] = ' ';
  1111.         }
  1112.         else
  1113.             retstr[count] = *string;
  1114.     }
  1115.     retstr[count] = NULL;
  1116.     return(retstr);
  1117. }
  1118. /****************************************************************************/
  1119. char *Rs(s)             /* strip trailing blanks from string  */
  1120. char s[];
  1121. {
  1122. int n;
  1123.     for (n=strlen(s)-1 ; n >= 0 && isspace(s[n]) ; n--)
  1124.         ;                /* find the last space in the string */
  1125.     s[n+1] = '\0';        /* plop a null char on top of it     */
  1126.     return(s);            /* return pointer to string          */
  1127. }
  1128. /****************************************************************************/
  1129. int Cmemb(a,b)  /*  is character "a" a member of string "b"  */
  1130. char  a, *b;
  1131. {
  1132.     while  (*b)                /* go until the null character */
  1133.         if (a == *b++)        /* looking for the character and bumping the pointer */
  1134.             return(1);        /* returning 1 if its found */
  1135.     return( (!a) ? 1 : 0 );    /* return 0 if "a" was a non-zero character */
  1136. }
  1137. /****************************************************************************/
  1138. StarDot(file_string)
  1139. char * file_string;
  1140. {
  1141. extern char filenames[N_FILES][MAX_FNAME_SIZE];
  1142. extern char fnames[N_FILES];
  1143. extern struct ffblk fblock;
  1144. extern struct dfree disk_space;
  1145.  
  1146. unsigned long int total_file_size = 0;
  1147. unsigned long int total_disk_free = 0;
  1148. int done;
  1149. int i = 0;
  1150.     file_string += 2;                        /* bump past -A switch */
  1151.  
  1152.     if( (done = findfirst(file_string,&fblock,0)) != 0) {/* Attempt 1st file read */
  1153.         fprintf(stderr,"No Files Found\n");
  1154.         exit(1);
  1155.     }
  1156.     while(!done && i < N_FILES) {        /* go until done or to many files */
  1157.         strcpy(&filenames[i][0],fblock.ff_name);/* copy names into array  */
  1158.         fname[i] = &filenames[i++][0];        /* copy pointer to name       */
  1159.  
  1160.         total_file_size += fblock.ff_fsize;    /* keep running total of filesizes */
  1161.  
  1162.         done = findnext(&fblock);            /* read next availables file info  */
  1163.     }
  1164.     if( i == N_FILES)
  1165.         fprintf(stderr,"Printing ONLY 1st %d Files\n", N_FILES);
  1166.  
  1167.     getdfree(0, &disk_space);                /* find free disk space */
  1168.     total_disk_free =    (     ((long)disk_space.df_bsec  *    /* convert to bytes */
  1169.                             (long)disk_space.df_sclus) *
  1170.                             (long)disk_space.df_avail);
  1171.  
  1172.     if((total_file_size * 2) >= total_disk_free) {
  1173.         fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
  1174.                         \nYou Have %lu bytes free\n",
  1175.                         total_file_size * 2, total_disk_free);
  1176.         exit(1);
  1177.     }
  1178.     return(i);            /* return new number of files */
  1179. }
  1180. /*****************************************************************************/
  1181. ReportMemoryError()
  1182. {
  1183.     fprintf(stderr,"Memory Allocation Error\n");
  1184.  
  1185.     if( TempName ) {            /* if there is a file to work on */
  1186.         EndTempFile();            /* Make sure file is closed */
  1187.         unlink( TempName );        /* Delete temporary file */
  1188.     }
  1189.  
  1190.     exit(1);
  1191. }
  1192. /*****************************************************************************/
  1193. ReadHeaderFile(header_file)
  1194. char *header_file;
  1195. {
  1196. extern char        header_buffer[MAX_HDR_BYTES];
  1197. extern int        header_lines;
  1198. int ch;
  1199. int i = 0;
  1200. int x = 0;
  1201. char *string;
  1202.  
  1203.     header_file += 2;        /* strip the "-h" from the string */
  1204.     if(( Hfile = fopen(header_file, "r")) == NULL) {
  1205.         fprintf(stderr,"Can't Open Header File %s\n",header_file);
  1206.         exit(1);            /* terminate abruptly */
  1207.     }
  1208.     else {
  1209. /* read entire file that is up to MAX_HDR_BYTES characters long */
  1210.         while( (ch = fgetc(Hfile)) != EOF) {
  1211.             header_buffer[i++] = (unsigned char) ch;
  1212.             if(i < MAX_HDR_BYTES)
  1213.                 continue;
  1214.             else
  1215.                 break;
  1216.         }
  1217.         header_buffer[i] = '\0';    /* terminate buffer */
  1218.  
  1219.         fclose(Hfile);        /* and close the file */
  1220.  
  1221.         for(x = 0, string = header_buffer; x <= i; x++) {
  1222.             if(*string++ == '\n')        /* count number of line feeds */
  1223.                 header_lines++;            /* tell the NewPage Function  */
  1224.         }
  1225.     }
  1226. }
  1227. /*****************************************************************************/
  1228. ReadResponseFile(response_file)
  1229. char *response_file;
  1230. {
  1231. char fpntr[80];                /* area for string to be read into */
  1232. extern char filenames[N_FILES][MAX_FNAME_SIZE];
  1233. extern char fnames[N_FILES];
  1234. extern struct ffblk fblock;
  1235. extern struct dfree disk_space;
  1236.  
  1237. unsigned long int total_file_size = 0;
  1238. unsigned long int total_disk_free = 0;
  1239.  
  1240. int i = 0;
  1241.  
  1242.     response_file += 2;    /* strip the "-@" from the string */
  1243.     if(( Rfile = fopen(response_file, "r")) == NULL) {
  1244.         fprintf(stderr,"Can't Open Response File %s\n",response_file);
  1245.         exit(1);            /* terminate abruptly */
  1246.     }
  1247.     else {
  1248. /* read a entire line from the Rfile that is up to 80 characters long */
  1249.         while(fgets(fpntr,80,Rfile) != NULL && i < N_FILES) {
  1250.             strtok(fpntr," \n");                /* strip to LF or space */
  1251.             strcpy(&filenames[i][0],fpntr);        /* copy names into array */
  1252.             fname[i] = &filenames[i++][0];        /* copy pointer to name */
  1253.  
  1254.             findfirst(fpntr,&fblock,0);            /* read file size in */
  1255.  
  1256.             total_file_size += fblock.ff_fsize;    /* keep running total of filesizes */
  1257.         }
  1258.         fclose(Rfile);        /* and close the file */
  1259.  
  1260.         getdfree(0, &disk_space);        /* find free disk space */
  1261.         total_disk_free =    ( ((long)disk_space.df_bsec * (long)disk_space.df_sclus) *
  1262.                                (long)disk_space.df_avail);
  1263.  
  1264.         if((total_file_size * 2) >= total_disk_free) {
  1265.             fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
  1266.                             \nYou Have %lu bytes free\n",
  1267.                             total_file_size * 2, total_disk_free);
  1268.             exit(1);
  1269.         }
  1270.         return(i);            /* return new number of files */
  1271.     }
  1272.     return(0);
  1273. }
  1274. /*****************************************************************************
  1275.     This routine is executed when the CONTROL-BREAK key combination is hit
  1276. *****************************************************************************/
  1277. c_break()
  1278. {
  1279.     fprintf(stderr,"Control-Break hit.  Program aborting ...\n");
  1280.  
  1281.     if( TempName ) {            /* if you created a file    */
  1282.         EndTempFile();            /* Make sure file is closed */
  1283.         unlink( TempName );        /* Delete temporary file    */
  1284.     }
  1285.     return(0);                    /* ABORT sequence           */
  1286. }
  1287. /*****************************************************************************/
  1288. file_stats(filename)
  1289. char *filename;
  1290. {
  1291. extern struct ffblk fblock;
  1292.  
  1293.     findfirst(filename,&fblock,0);        /* read data into structure     */
  1294.  
  1295. /* ------------------- Show date in standard format --------------------*/
  1296.  
  1297.     sprintf(file_date_buff,"%02d-%02d-%02d",
  1298.         ((fblock.ff_fdate >> 5) & 0x0f),   /* month     */
  1299.         (fblock.ff_fdate & 0x1f)       ,   /* day       */
  1300.         ((fblock.ff_fdate >> 9) + 80  ));  /* year      */
  1301.  
  1302. /* -----------------   Show time in 12 Hour Format   ------------------- */
  1303.     if ( (fblock.ff_ftime >> 0x0b) <= 12)
  1304.     {
  1305.         sprintf(file_time_buff,"%02d:%02d",
  1306.         (fblock.ff_ftime >> 0x0b),
  1307.         ((fblock.ff_ftime >> 5 ) & 0x3f ));  /* minutes   */
  1308.     }
  1309.     else
  1310.     {
  1311.         sprintf(file_time_buff,"%02d:%02d",
  1312.         ((fblock.ff_ftime >> 0x0b) - 12),
  1313.         ((fblock.ff_ftime >> 5 ) & 0x3f ));  /* minutes   */
  1314.     }
  1315. /* ------------------     Decipher whether its AM or PM  ---------------- */
  1316.     if ( (fblock.ff_ftime >> 0x0b) < 12)
  1317.         strcat(file_time_buff," am");    /* for AM */
  1318.     else
  1319.         strcat(file_time_buff," pm");    /* for PM */
  1320. }
  1321. /*************************************************************************/