home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / CPR34SRC.ZIP / CPR.C < prev    next >
C/C++ Source or Header  |  1991-08-01  |  75KB  |  2,358 lines

  1. /*
  2.      CPR.C       " Prints 'C' Files with Table of Contents "
  3.                      "             AND LOTS MORE               "
  4.  
  5.      Microsoft C Version 6.0
  6.  
  7.      Note:  Turbo C Version 1.0 or 1.5 is available as CPR31.ARC 
  8.               in Borland Forum
  9.  
  10. Originally Written by :
  11.          Paul Breslin
  12.          Human Computing Resources Corp.
  13.          10 South Mary Street
  14.          Toronto, Ontario
  15.          Canada, M4Y 1P9
  16.  
  17. Modified by :
  18.         Lance E. Shepard     Rick Wise               Blake McBride
  19.         CCI & RIT            CALCULON Corp.          3900 SW 52nd Ave. #803
  20.         Rochester, NY        Rockville, MD 20850     Pembroke Park, FL 33023
  21.  
  22.         John Stidd           Dale Loftis             Tom Hiscox
  23.         1570 Neston Way      3020 Yorba Linda #F-16  136 Knorr Road
  24.         Los Altos, CA 94022  Fullerton, CA 92631     Monroe, CT 06468  72106,3307
  25.  
  26.         Dave Perkowski [70650,1420]
  27.         Argo Data Resource Corp.
  28.         15301 Dallas Prkwy.
  29.         Dallas, TX 75248
  30.  
  31. Special Notes:
  32.      Compiles with the /AL large model switch to ensure enough
  33.      space for the Table of Contents.  In MSC v5.1+. malloc will default 
  34.      to _fmalloc or _nmalloc depending on compile line switch.
  35.  
  36.      Tab stops on this version source code have been fully expanded to spaces
  37.      This takes more space but eliminates the mess when you load it into
  38.      your tab stops.
  39.  
  40. */
  41.  
  42. /* *************************************************************************
  43. **                        Program Revision History
  44. **
  45. **  By Dale Loftis
  46. **  10-3-87   Changed WIDTH to 132, Tabs are now every 4, modified so
  47. *             that temporary file is deleted if control - break is hit,
  48. **             Improved the clarity of the instructions if no parmeters
  49. **              are given.
  50. **
  51. **  10-17-87  Changed so that no blank lines are printed in between structures.
  52. **
  53. **  11-06-87  Added -@ RESPONSE FILE feature since you couldn't fit all the
  54. **             filenames onto the command line, upto 400 files can be printed.
  55. **
  56. **            Also adding the "Reading file # x of y" string and made program
  57. **             check the amount of free disk space before writing the files
  58. **             as the program would write the output file and run out of disk
  59. **             space and just put alot of junk on the disk.
  60. **
  61. **  11-08-87  Ver 1.0    Added -h HEADER FILE, -* "Print All 'C' Files,
  62. **                             -x Extra Lines and Program Version Number
  63. **
  64. **  01-10-88  Ver 1.1    Added call to setvbuf() to speed up file access.
  65. **
  66. **  01-25-88  Ver 1.2    Added -t  for option of just table of contents list
  67. **
  68. **  01-29-88  Ver 1.3    Fixed Bug.  funcname () would not be put in Table of
  69. **                         Contents because of space between funcname and ().
  70. **
  71. **  04-26-88  Ver 1.4    Added -p* option for starting page number and changed
  72. **                       Table of Contents so File Date and Time Shown.
  73. **
  74. **  05-12-88  Ver 3.0    Added -q* option to print files by section number
  75. **                       rather than by page number.
  76. **                       Added -t- option to suppress the Table of Contents
  77. **
  78. **  07-18-88  Ver 3.1    Fixed bug in printing by section where form feed was
  79. **                       not being output at the top of the file.
  80. **
  81. **  (T. Hiscox)
  82. **  03-25-89  Ver 3.2    Translation to Microsoft C Version 5.1 
  83. **                       Sort by actual function name(not case sensitive)
  84. **                       ignoring type cast, print aligned with function name.
  85. **                       {No messages on Warning Level 3 !!} 
  86. **
  87. **  ( T. Hiscox)
  88. **  09-01-89  Ver 3.3    Add Cross Reference of function calls between modules
  89. **                       Printer Support for Epson and Hewlett Packard Deskjet
  90. **
  91. **  (D. Perkowski)
  92. **  08-01-91  Ver 3.4     Added support for OS/2, ANSI C decls and aligned
  93. **                                 braces.
  94. */
  95.  
  96. /* --------------------------------------------------------------------- */
  97. /*
  98.          Include Files for Library Function Prototypes
  99. */
  100. #ifdef OS2
  101. #define INCL_DOSFILEMGR
  102. #define INCL_ERRORS
  103. #include <os2.h>
  104. #endif
  105. #include  <stdio.h>
  106. #include  <stdlib.h>
  107. #include  <fcntl.h>
  108. #include  <malloc.h>
  109. #include  <dos.h>
  110. #include  <conio.h>
  111. #include  <time.h>
  112. #include  <string.h>
  113. #include  <ctype.h>
  114. #include  <io.h>
  115.  
  116. /* --------------------------------------------------------------------- */
  117. /*
  118.          Some Valuable Definitions
  119. */
  120. #define      O_RAW  O_BINARY                  /* Handle File as Binary       */
  121.  
  122. #define      TEMPORARY_FILENAME   "CPR$.TMP"  /* temporary file name (always)*/
  123.  
  124. #define      MAJOR_VERSION  3                 /* Current Software Version #   */
  125. #define      MINOR_VERSION  4
  126.  
  127. #define      MAX_S          256      /* Maximum string length        */
  128. #define      LENGTH         60       /* Default Page Length          */
  129. #define      WIDTH          132      /* Default page width           */
  130. #define      N_FILES        400      /* Maximum number of files      */
  131. #define      TOC_LEN        1024     /* Max Table of Contents entries*/
  132. #define      MAX_FNAME_SIZE 50       /* Max filename length in response file */
  133. #define      MAX_HDR_BYTES  500      /* Max bytes in header file     */
  134. #define      HEADER_SIZE    3        /* Header is 3 lines big        */
  135. /* -------------------------------------------------------------------------
  136. /* These Macros are used to determine valid characters for Table of Contents
  137. */
  138.  
  139. /* returns true if letter, digit, '_' , '*', or ' '      */
  140. #define isidchr(c)      (isalnum(c) || (c == '*') || (c == '_') || (c == ' '))
  141.  
  142. /* returns true if letter, digit, '_', '*', '\t' or '\n' */
  143. #define isiechr(c)      (isidchr(c) || c=='*' || c=='\t' || c=='\n')
  144.  
  145. /* returns true is letter, digit, '_', '*'               */  
  146. #define isnamechr(c)    (isalnum(c) || (c == '*') || (c == '_') )
  147.  
  148. /* --------------------------------------------------------------------- */
  149. /*
  150.          Internal Program Function Prototypes
  151. */
  152. void  main(int argc,char * *argv);
  153. void  Usage(void );
  154. void  StartTempFile(void );
  155. void  EndTempFile(void );
  156. void  DumpTempFile(void );
  157. int store_mod_call(struct cptr *modlist[],int m1,int m2);
  158. int store_call(struct tnode *stree,int tindex);
  159. int store_uses(struct tnode *stree,int tindex,int p);
  160. int search_call(struct tnode *stree, int tindex, struct cptr **cp);
  161. int search_use(struct tnode *stree, int tindex, struct cptr **cp);
  162. void module_map(struct cptr *modlist[],char *title);
  163. void  proc_map( int ( *sroutine )( struct tnode *proctree,
  164.                                     int tproc, struct cptr **pc ), char *title );
  165. void  DumpCrossReference(void);
  166. void  Done(void );
  167. void  List(void );
  168. void  NewPage(void );
  169. void  NewFile(void );
  170. int   PutLine(char *l);
  171. void  NewFunction(void );
  172. void  BreakPage(void );
  173. void  PutHeader(void );
  174. int   keycomp( char *elem1, char *elem2);
  175. void  write_xref(char *s);
  176. int   LooksLikeFunction(char *s);
  177. void   AddToTableOfContents(void );
  178. void   DumpTableOfContents(void );
  179. char   *strupper(char *str);
  180. char   *root_name(char *ns);
  181. void   SortTableOfContents(void );
  182. char   *EndComment(char *p, int *flag);
  183. char   *EndString(char *p,int *flag);
  184. char   *substr1(char *string,int start,int end);
  185. char   *expand(char *string);
  186. char   *Rs(char *s);    
  187. int    Cmemb(char a,char *b);
  188. int    StarDot(char *file_string);
  189. void   ReportMemoryError(void );
  190. void   ReadHeaderFile(char *header_file);
  191. int    ReadResponseFile(char *response_file);
  192. int    c_break(void);
  193. void   file_stats(char *filename);
  194. int   printer_code_init(void);
  195. void  normal_print(void);
  196. void  emphasized_print_on(void);
  197. void  emphasized_print_off(void);
  198. void  print_double_width(void);
  199. void  compressed_print(void);
  200. void  new_print_page(void);
  201. void  underline_on(void);
  202. void  underline_off(void);
  203. void  pspace(int ns);
  204. char *strupper(char *str);
  205. char *strsave(char *s);
  206. void strfree(char *s);
  207. char *strcompress( char *s);
  208. int  CrossRefFunction( char *s);
  209. int searchtree_index(struct tnode *stree,char *word,int tindex);
  210. int searchtree_word(struct tnode *stree,char *word,int *tindex);
  211. struct tnode *entertree(struct tnode *stree,char *word,int *lindex,int *tindex);
  212. int FindFirst( char *filename, unsigned attr, struct find_t *finfo );
  213. int FindNext( struct find_t *finfo );
  214. int FindClose( void );
  215. int GetDiskFree( unsigned drive, struct diskfree_t *disk_space );
  216.  
  217. /* -------------------------------------------------------------------- */
  218. /*
  219.          Global Variables
  220. */
  221. FILE  *TempFile;                 /* Program Temporary File       */
  222. FILE  *File;                     /* Current File being worked on */
  223. FILE  *Rfile;                    /* Response File handle         */
  224. FILE  *Hfile;                    /* Header   File handle         */
  225.  
  226. struct find_t fblock;             /* struct used for calculating file size */
  227. struct diskfree_t disk_space;     /* struct used for finding free disk space */
  228.  
  229. char  file_time_buff[20];      /* file time is placed here      */
  230. char  file_date_buff[20];      /* file date is placed here      */
  231.  
  232. int    Braces;                 /* Keeps track of brace depth    */
  233. int    LineNumber;             /* Count output lines           */
  234. int    PageNumber = 1;         /* You figure this one out       */
  235. int    SectionNumber = 1;      /* and this one to               */
  236. int    PageLength = LENGTH;    /* Normal paper length           */
  237. int    PageWidth  = WIDTH;     /* normal page width             */
  238. int    OnePerPage = 0;         /* non-zero puts 1 function/page */
  239. int    NumLines   = 0;         /* non-zero puts line # in file  */
  240. int    Number     = 1;
  241. int    WantSorted = 1;         /* Sort the table of contents   */
  242. int    PageEnd;             /* Accounts for space at bottom */
  243. int    InComment;           /* Indicates if inside Comment  */
  244. int    InXComment;          /* Indicates if inside Comment (Xref) */
  245. int    InString;            /* Indicates if inside String   */
  246. int    InXString;          /*  Indicates in String for Xref Function */
  247. int    double_strike;       /* # of times + 1 to write filename             */
  248. int    header_flag;         /* non-zero enables print codes/Dates/Page #'s  */
  249. int    header_lines;        /* number of extra lines from header file       */
  250. int    extra_lines;         /* non-zero enables extra lines after functions */
  251. int    table_contents;      /* non-zero indicates Table of Contents Only    */
  252. int    sectionflg;          /* non-zero indicates print by section          */
  253. int    nprinter = 1;        /* zero = Epson, 1 = Deskjet, 2 = ASCII(none)   */
  254.  
  255. unsigned long   memfree;    /* amount of local memory left for file buffer  */
  256.  
  257. char   *TempName;           /* pointer to temporary filename   */
  258. char   *fname[N_FILES];     /* file names to be worked on      */
  259. char   *STDIN = "\n";       /* special string pointer value to */
  260. /* flag a file as being stdin      */
  261. char   *Name;               /* Current file name               */
  262. char   *ProgName;           /* This programs Path and Name     */
  263.  
  264. char   *Toc[TOC_LEN];       /* pointers to files in TOC        */
  265. int TocPages[TOC_LEN];      /* page numbers                    */
  266. int TocIndex[TOC_LEN];
  267. int TocCount;               /* index into TOC arrays           */
  268. char  *cproc;
  269. int   nextf;                /* index into fname[]                */
  270.  
  271. char   header_buffer[MAX_HDR_BYTES]; /* 500 byte buffer for user defined Page Headers */
  272. char   FunctionName[255];            /* Work area for parsing Func names */
  273. char   Todayv[45];                   /* Today's Time and Date        */
  274. /* --------------------------------------------------------------------- */
  275. /*
  276.       The filenames[N_FILES][25] array allocates an array capable of holding
  277.      N_FILES filenames that are up to 25 characters long.
  278.  
  279.       Each filename in DOS can be 12 characters long and the response file
  280.      has a CRLF with each line and we also need a terminating zero byte
  281.      bringing the count up to 15. MAX_FNAME_SIZE bytes are provided for a
  282.      possible path
  283. */
  284. /* --------------------------------------------------------------------- */
  285. /* char *filenames[N_FILES]; */
  286.  
  287. #ifdef OS2
  288. static HDIR hDir;
  289. static FILEFINDBUF FileInfo;
  290. #endif
  291.  
  292. /* --------------------------------------------------------------------- */
  293. /*
  294. **  The following string is the definition of tab stops.  Every 'T' is a
  295. **  tab, any other character is not.  It is currently defined as a tab
  296. **  every 3 spaces.  The comment below helps if you want to modify this,
  297. **  each row being 0+n, 50+n, 100+n, and 150+n, where n is the number
  298. **  above the declaration.  Don't try to number each row with a comment,
  299. **  because you'll notice that the '\'s make it one big string.
  300. */
  301. char   *TabDef = "\
  302. --T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T\
  303. --T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T";
  304. /* ------------------------------------------------------------------------ */
  305. #define  PRINTERS 3
  306.  
  307. struct   esc_codes   {
  308.     char  *id;
  309.     char  *prt_init;
  310.     char  *prt_compress;
  311.     char  *prt_normal;
  312.     char  *prt_double_width_on;
  313.     char  *prt_double_width_off;
  314.     char  *prt_emphasize_on;
  315.     char  *prt_emphasize_off;
  316.     char  *prt_new_page;
  317.     char  *prt_underline_on;
  318.     char  *prt_underline_off;
  319. };
  320.  
  321. struct   esc_codes   print_code[PRINTERS] = {
  322.     {"Epson FX","\x01B\x040","\x00F","\x012","\x00E","\x014","\x01B\x045","\x01b\x046","\x00C","\x01B\x02D\x000","\x01B\x02D\x001"},
  323.     {"DeskJet ","\x01B(s16.67h0B\x01b&a10L",
  324.         "\x0",
  325.         "\x01B(s16.67h0B",
  326.         "\x01b(s5h3B",
  327.         "\x01B(s16.67h0B",
  328.         "\x01b(s3B",
  329.         "\x01b(s0B",
  330.         "\x01B&l0H",
  331.         "\x01b&d2D",
  332.         "\x01b&d@"},
  333.     {"ASCII Text","","","","","","","","\x0C","",""},
  334. };
  335.  
  336. struct esc_codes  *printer;
  337.  
  338. typedef char ckey_type[10];
  339. ckey_type ckeys[] =
  340.   {"auto     ",
  341.     "break    ",
  342.     "case     ",
  343.     "cdecl    ",
  344.     "char     ",
  345.     "const    ",
  346.     "continue ",
  347.     "default  ",
  348.     "do       ",
  349.     "double   ",
  350.     "else     ",
  351.     "enum     ",
  352.     "extern   ",
  353.     "far      ",
  354.     "float    ",
  355.     "for      ",
  356.     "fortran  ",
  357.     "goto     ",
  358.     "huge     ",
  359.     "if       ",
  360.     "int      ",
  361.     "interrupt",
  362.     "long     ",
  363.     "near     ",
  364.     "pascal   ",
  365.     "register ",
  366.     "return   ",
  367.     "short    ",
  368.     "signed   ",
  369.     "sizeof   ",
  370.     "static     ",
  371.     "struct   ",
  372.     "switch   ",
  373.     "typedef  ",
  374.     "union    ",
  375.     "unsigned ",
  376.     "void     ",
  377.     "volatile ",
  378.     "while    "};
  379. #define  KEYSIZE  sizeof(ckeys) / sizeof(ckey_type)
  380.  
  381. /*------------------------------- tree types ------------------*/
  382.  
  383. struct cptr
  384. {
  385.     struct cptr  *next_ptr;
  386.     int   proc;
  387. };
  388.  
  389. struct entrytype
  390. {
  391.     char         *proc;
  392.     int          module;
  393.     unsigned int index;
  394.     struct   cptr  *calls;
  395.     struct   cptr  *uses;
  396. };
  397.  
  398. struct tnode
  399. {
  400.     struct entrytype *this_entry;
  401.     struct tnode     *left;
  402.     struct tnode     *right;
  403. };
  404. struct   tnode *proctree;
  405. struct   cptr *modcall[N_FILES];
  406. struct   cptr *moduse[N_FILES];
  407. int   module_index,proc_index,last_module_index,last_proc_index;
  408. struct   call_type
  409. {
  410.     int   module;
  411.     int   proc;
  412.     char  *call;
  413. };
  414.  
  415. #define  MAX_XREF 6144
  416. struct call_type  call_list[MAX_XREF];
  417. int   num_call;
  418. /* ------------------------------------------------------------------------ */
  419.  
  420. /****************************************************************************/
  421. void main( int argc, char **argv )
  422. {
  423.     unsigned long int total_disk_free = 0;
  424.     unsigned int   ch;
  425.     register int    i;
  426.     long    thetime;
  427.  
  428.     nextf = 0;
  429.     double_strike = 1;            /* default to no double strike       */
  430.     header_flag   = 1;            /* default to codes and headers      */
  431.     header_lines  = 0;            /* no extra lines from header file   */
  432.     extra_lines   = 0;            /* no extra lines after functions    */
  433.     cproc = NULL;
  434.     last_proc_index = last_module_index = 0;
  435.     num_call = 0;
  436.     TocCount = 0;
  437.     proctree=NULL;
  438.     memset(modcall,'\0',sizeof(modcall) );
  439.     memset(moduse,'\0',sizeof(moduse) );
  440.  
  441.     ProgName = strupr(argv[0]);   /* grab pointer to the programs name */
  442.  
  443.     time(&thetime);               /* grab the DOS time and date        */
  444.     strcpy(Todayv,ctime(&thetime));  /* convert to ascii (LF at END OF STRING) */
  445.     strtok(Todayv,"\n");          /* strip the annoying LF off         */
  446.  
  447.     if (argc == 1)                /*if only the program name given     */
  448.         Usage();                   /* if no args, show instructions     */
  449.  
  450.     fprintf(stderr,"\nCPR - A C Source Code Printing and Cross Reference Utility\n");
  451.     fprintf(stderr,"Version %d.%d  August 1991\n\n",
  452.                                                             MAJOR_VERSION, MINOR_VERSION );
  453.  
  454.     for (i = 1; i < argc; i++) 
  455.     {  /* other parse command line          */
  456.         if (argv[i][0] == '-')  
  457.         {  /* check for switch flag "-"         */
  458.             switch (toupper(argv[i][1])) 
  459.             { /* and go thru the switches   */
  460.  
  461.                 case '@':               /* Response file */
  462.                     nextf = ReadResponseFile(argv[i]);
  463.                     break;
  464.  
  465.                 case 'A':               /* "*.???" Print all specified files */
  466.                     nextf = StarDot(argv[i]);
  467.                     break;
  468.  
  469.                 case 'C':               /* Print codes/Dates/Time and page # */
  470.                     header_flag = 0;
  471.                     break;
  472.  
  473.                 case 'D':               /* Double Strike function names      */
  474.                     double_strike = 3;
  475.                     break;
  476.  
  477.                 case 'H':               /* Header file                       */
  478.                     ReadHeaderFile(argv[i]);
  479.                     break;
  480.  
  481.                 case 'L':                        /* Number of lines per page          */
  482.                     if ( ! argv[i][2]) 
  483.                     {                /* if -L ?? (ie.. a space)           */
  484.                         if (++i >= argc)                 /* see if another argument           */
  485.                             Usage();                      /* if no then print Help             */
  486.  
  487.                         if ( ! isdigit (argv[i][0]))     /* is it a number?       */
  488.                             Usage();                      /* No! Print Help        */
  489.  
  490.                         PageLength = atoi (argv[i]);     /* assign number         */
  491.                     }
  492.                     else 
  493.                     {      /* Switch came as -L?? form (with no space)      */
  494.                         if (!isdigit(argv[i][2]))        /* is it a number?       */
  495.                             Usage();             /* No! Print Help        */
  496.  
  497.                         PageLength = atoi(&argv[i][2]);  /* assign number         */
  498.                     }
  499.                     break;
  500.  
  501.                 case 'N':               /* Number Source Lines               */
  502.                     NumLines = 1;
  503.                     break;
  504.  
  505.                 case 'O':               /* 1 function per page               */
  506.                     OnePerPage = 1;
  507.                     break;
  508.  
  509.                 case 'P':               /* Starting Page Number              */
  510.                     if ( ! argv[i][2]) 
  511.                     {          /* if -P ?? (ie.. a space)           */
  512.                         if (++i >= argc)           /* see if another argument           */
  513.                             Usage();                /* if no then print Help             */
  514.                         if ( ! isdigit (argv[i][0]))  /* is it a number?       */
  515.                             Usage();                   /* No! Print Help        */
  516.                         PageNumber = atoi (argv[i]);  /* assign number         */
  517.                     }
  518.                     else 
  519.                     {      /* Switch came as -P?? form (with no space)      */
  520.                         if (!isdigit(argv[i][2]))     /* is it a number?       */
  521.                             Usage();                   /* No! Print Help        */
  522.                         PageNumber = atoi(&argv[i][2]);  /* assign number         */
  523.                     }
  524.                     break;
  525.  
  526.                 case 'Q':               /* Print by Section                  */
  527.                     if ( ! argv[i][2]) 
  528.                     {             /* if -Q ?? (ie.. a space)           */
  529.                         if (++i >= argc)              /* see if another argument           */
  530.                             Usage();                      /* if no then print Help             */
  531.                         if ( ! isdigit (argv[i][0]))     /* is it a number?       */
  532.                             Usage();                      /* No! Print Help        */
  533.                         SectionNumber = atoi (argv[i]);  /* assign number         */
  534.                     }
  535.                     else 
  536.                     {      /* Switch came as -Q?? form (with no space)      */
  537.                         if (!isdigit(argv[i][2]))        /* is it a number?       */
  538.                             Usage();                      /* No! Print Help        */
  539.                         SectionNumber=atoi(&argv[i][2]); /* assign number         */
  540.                     }
  541.                     sectionflg = 1;
  542.                     break;
  543.  
  544.                 case 'S':               /* Sorted Table of Contents          */
  545.                     WantSorted = 0;
  546.                     break;
  547.  
  548.                 case 'T':               /* Print Table of Contents Only      */
  549.                     table_contents = 1;        /* enable flag                       */
  550.                     if( argv[i][2] == '-')     /* if disabling TOC                  */
  551.                         table_contents = -1;    /* disable it                        */
  552.                     break;
  553.  
  554.                 case 'W':                                 /* Page Width                        */
  555.                     if ( ! argv[i][2]) 
  556.                     {             /* if -W ?? (ie.. a space)           */
  557.                         if (++i >= argc)              /* see if another argument           */
  558.                             Usage();                   /* if no then print Help             */
  559.                         if ( ! isdigit (argv[i][0]))  /* is it a number?       */
  560.                             Usage();                   /* No! Print Help        */
  561.                         PageWidth = atoi (argv[i]);   /* assign number         */
  562.                     }
  563.                     else 
  564.                     {                           /* Switch came as -W?? form (with no space)      */
  565.                         if (!isdigit(argv[i][2]))     /* is it a number?       */
  566.                             Usage();                   /* No! Print Help        */
  567.                         PageWidth = atoi(&argv[i][2]);   /* assign number         */
  568.                     }
  569.                     break;
  570.  
  571.                 case 'X':               /* Extra Lines after Functions       */
  572.                     extra_lines = 1;
  573.                     break;
  574.  
  575.                 case '\0':              /* End of string?(out of enviroment) */
  576.                     if (nextf >= N_FILES) 
  577.                     {
  578.                         fprintf (stderr, "%s: too many files\n", argv[0]);
  579.                         exit (1);
  580.                     }
  581.                     fname[nextf++] = STDIN;    /* any in excess goes to STDIN   */
  582.                     break;
  583.  
  584.                 default:                /* No arguments given            */
  585.                     Usage();             /* show program instructions     */
  586.                     break;
  587.             }
  588.         }
  589.         else 
  590.         {      /* Argument (argv[i]) wasn't a switch parmeter           */
  591.             if (nextf >= N_FILES) 
  592.             {
  593.                 fprintf (stderr, "%s: too many files\n", argv[0]);
  594.                 exit (1);
  595.             }
  596.             fname[nextf++] = argv[i];  /* copy pointer to filename          */
  597.         }
  598.     }
  599.  
  600.     if ( ! nextf)           /* No files were specified                   */
  601.         fname[nextf++] = STDIN; /* so use STDIN as the input file            */
  602.  
  603.     PageEnd = PageLength - (1 + PageLength / 20);
  604.  
  605.     StartTempFile();                    /* open temporary Output file               */
  606.  
  607.     printer_code_init();
  608.     for (i = 0; i < nextf; i++) 
  609.     {       /* walk thru file list               */
  610.         if (fname[i] == STDIN) 
  611.         {         /* if no files                       */
  612.             File = stdin;                 /* assign stdin as input             */
  613.             Name = "Standard Input";      /* assign name for printout          */
  614.             fprintf(stderr,"Accepting Input from STDIN, ^Z to END\n");
  615.         }
  616.         else  
  617.         {                          /* there was a filename              */
  618.             if( (File = fopen( Name = fname[i], "r" )) == NULL )  
  619.             {
  620.                 fprintf (stderr, "%s: Can't open file \"%s\"\n",
  621.                     ProgName, Name );
  622.                 continue;                  /* keep going if not found           */
  623.             }
  624.             else 
  625.             {                        /* file opened OK so read            */
  626.                 fprintf(stderr, "\nReading File #%3d of %3d: \" %s \"",
  627.                     i+1, nextf, fname[i]);
  628.  
  629.                 memfree = _memmax();              /* compute amount of free memory */
  630.                 memfree = ( (memfree > 32767L) ?  /* if to much memory then    */
  631.                     32767L  :          /* set max for setvbuf       */
  632.                     memfree );       /* else take as much as u can*/
  633.  
  634.                 if( setvbuf(File, NULL, _IOFBF, (int) memfree) != 0) 
  635.                 {
  636.                     fprintf(stderr,"Input Buffer failed to allocate.\n");
  637.                 }
  638.             }
  639.         }
  640.         if ( cproc ) free(cproc);
  641.         cproc = NULL;
  642.         module_index = i;
  643.         List();              /* Read File in and process data             */
  644.  
  645.         if (File != stdin) 
  646.         { /* if it's not STDIN                         */
  647.             fclose(File);     /* close file & deallocate buffer            */
  648.             fprintf(stderr, " Table Entries: %4d  Cross Refs: %4d",TocCount,num_call);
  649.         }
  650.     }
  651.  
  652.     if( PageNumber > 1 || LineNumber > 0 )
  653.         BreakPage();
  654.  
  655.     EndTempFile();          /* Close Temporary File                     */
  656.  
  657.     fprintf(stderr,"\n\n");
  658.  
  659.     GetDiskFree(0,&disk_space);
  660.     total_disk_free = ( ( (long)disk_space.bytes_per_sector *   /* bytes per sector    */
  661.         (long)disk_space.sectors_per_cluster) *   /* sectors per cluster */
  662.         (long)disk_space.avail_clusters);      /* clusters available  */
  663.     FindFirst(TEMPORARY_FILENAME,0,&fblock);
  664.     if(fblock.size >= total_disk_free) 
  665.     {   /* see if copy can be output */
  666.         fprintf(stderr,"Insufficient Disk Space!\n\
  667.                    \nMinimum of %lu bytes needed.\
  668.                    \n%lu bytes are available\n\
  669.                    \nDo You wish to continue? (Y/N)",
  670.             fblock.size, total_disk_free);
  671.  
  672.         do 
  673.         {
  674.             ch =  toupper( getche() );
  675.         }
  676.         while((ch != 'Y') && (ch != 'N'));
  677.  
  678.         if(ch != 'Y')
  679.             Done();              /* Delete Temporary File             */
  680.  
  681.         fprintf(stderr,"\n\n");
  682.     }
  683.  
  684.  
  685.     if((!table_contents) ||       /* if TOC and file enabled           */
  686.         (table_contents == 1))     /* or TOC only     enabled           */
  687.         DumpTableOfContents();     /* Print Table of Contents           */
  688.  
  689.     DumpCrossReference();
  690.  
  691.     if((!table_contents) ||       /* if TOC and file enabled           */
  692.         (table_contents == -1))    /* or no TOC                         */
  693.         DumpTempFile();            /* then dump the file                */
  694.  
  695.  
  696.     Done();                    /* Clean things up and leave         */
  697. }
  698. /****************************************************************************/
  699. void Usage( void )
  700. {
  701.     fprintf (stderr,"\nUsage: %s SWITCHES filename [...]", ProgName );
  702.     fprintf (stderr,"\n----------------------------- VERSION %d.%d SWITCHES ------------------------\n",MAJOR_VERSION,MINOR_VERSION);
  703.     fprintf (stderr,"           -@*    Replace * with Response Filename (1 filename per line    )\n");
  704.     fprintf (stderr,"           -a*    Replace * with Drive Wildcard\n");
  705.     fprintf (stderr,"           -c     Printer Codes/Dates/Page #'s off (default is Enabled     )\n");
  706.     fprintf (stderr,"           -d     Double Strike Printing Enabled   (default is Disabled    )\n");
  707.     fprintf (stderr,"           -h*    Replace * with Header Filename\n");
  708.     fprintf (stderr,"           -l##   Replace ## with PageLength       (default = %3d          )\n",LENGTH);
  709.     fprintf (stderr,"           -n     Numbers Source Lines             (Resets to 1 w/each file)\n");
  710.     fprintf (stderr,"           -o     Places 1 function on a Page      (default is multiple    )\n");
  711.     fprintf (stderr,"           -p*    Replace * with starting Page Number\n");
  712.     fprintf (stderr,"           -q*    Replace * with starting Section Number\n");
  713.     fprintf (stderr,"           -s     Sort Table of Contents by Page # (default is Func. Name  )\n");
  714.     fprintf (stderr,"           -t     Print Table of Contents Only     (-t- suppress's Table   )\n");
  715.     fprintf (stderr,"           -w##   Replace ## with Width            (default = %3d          )\n",WIDTH);
  716.     fprintf (stderr,"           -x     Enables Extra Lines after Functions (default is Disabled )\n");
  717.     fprintf (stderr,"          [...]   Means multiple filenames may be listed\n\n");
  718.     fprintf (stderr,"               Response Files should have 1 filename per line up to %d      \n",MAX_FNAME_SIZE-1);
  719.     fprintf (stderr,"         characters followed by 1 CRLF and may contain up to %d filenames.  \n\n",N_FILES);
  720.     fprintf (stderr,"               Header Files contain the Strings to Print at the top of      \n");
  721.     fprintf (stderr,"         every page of the listing, entire file can be up to %d bytes.",MAX_HDR_BYTES);
  722.     exit(1);
  723. }
  724.  
  725. /****************************************************************************/
  726. void StartTempFile( void )
  727. {
  728.     TempName = TEMPORARY_FILENAME;         /* Temporary Filename */
  729.  
  730.     if( (TempFile = fopen(TempName, "w")) == NULL ) 
  731.     {
  732.         fprintf (stderr, "%s: Can't open temp file!\n", ProgName);
  733.         exit(1);
  734.     }
  735. }
  736.  
  737. /****************************************************************************/
  738. void EndTempFile( void )
  739. {
  740.     fclose (TempFile);
  741. }
  742.  
  743. /****************************************************************************/
  744. void DumpTempFile( void )
  745. {
  746.     int     fd,n;
  747.     char    buff[1025];
  748.  
  749.     if ((fd = open (TempName, O_RDONLY | O_RAW)) == -1) 
  750.     {
  751.         fprintf (stderr, "%s: can't open temp file\n", ProgName);
  752.         exit (1);
  753.     }
  754.  
  755.     fprintf(TempFile,"%s",printer->prt_init);
  756.     while ((n = read (fd, buff, 1024)) != 0) 
  757.     {
  758.         if (write (1, buff, n) == -1) 
  759.         {
  760.             fprintf (stderr, "%s: write error (1)\n", ProgName);
  761.             exit (1);
  762.         }
  763.     }
  764. }
  765.  
  766. /****************************************************************************/
  767. /* Enter module list with m1 calling or using m2 */
  768. int store_mod_call( struct cptr *modlist[], int m1, int m2 )
  769. {
  770.     struct cptr *pc,*cp;
  771.  
  772.     if( (pc = ( struct cptr *)malloc( sizeof(struct cptr) )) == NULL ) exit(0);
  773.     pc->next_ptr = NULL;
  774.     pc->proc = m2;
  775.     if ( modlist[m1] ) 
  776.     {
  777.         cp = modlist[m1];
  778.         do 
  779.         {
  780.             if ( cp->proc == m2 ) 
  781.             {
  782.                 free(pc);
  783.                 return(1);
  784.             }
  785.             if ( cp->next_ptr )
  786.                 cp = cp->next_ptr;
  787.             else
  788.                 break;
  789.         } while ( cp );
  790.         cp->next_ptr = pc;
  791.     }
  792.     else
  793.         modlist[m1] = pc;
  794.     return(1);
  795. }
  796.  
  797. /****************************************************************************/
  798. /* Enter tree with tindex, stores proc_index and module_index in Calls*/
  799. int store_call( struct tnode *stree, int tindex )
  800. {
  801.     struct cptr *pc,*cp;
  802.  
  803.     if ( stree ) 
  804.     {
  805.         if (stree->this_entry->index == tindex) 
  806.         {
  807.             if ( (pc = ( struct cptr *)malloc( sizeof(struct cptr) )) == NULL ) exit(0);
  808.             pc->next_ptr = NULL;
  809.             pc->proc = proc_index;
  810.             if ( stree->this_entry->calls ) 
  811.             {
  812.                 cp = stree->this_entry->calls;
  813.                 do 
  814.                 {
  815.                     if ( cp->proc == proc_index ) 
  816.                     {
  817.                         free(pc);
  818.                         return(1);
  819.                     }
  820.                     if ( cp->next_ptr )
  821.                         cp = cp->next_ptr;
  822.                     else
  823.                         break;
  824.                 } while ( cp );
  825.                 cp->next_ptr = pc;
  826.             }
  827.             else stree->this_entry->calls = pc;
  828.             return(1);
  829.         }
  830.         else 
  831.         {
  832.             if(store_call(stree->left,tindex) == 0)
  833.                 store_call(stree->right,tindex);
  834.         }
  835.     }
  836.     return(0);
  837. }
  838.  
  839. /****************************************************************************/
  840. /* Enter tree with tindex, stores proc_index and module_index in Uses area*/
  841. int store_uses( struct tnode *stree, int tindex, int p )
  842. {
  843.     struct cptr *pc,*cp;
  844.  
  845.     if ( stree ) 
  846.     {
  847.         if (stree->this_entry->index == tindex) 
  848.         {
  849.             if ( (pc = ( struct cptr *)malloc( sizeof(struct cptr) )) == NULL ) exit(0);
  850.             pc->next_ptr = NULL;
  851.             pc->proc = p;
  852.             if ( stree->this_entry->uses ) 
  853.             {
  854.                 cp = stree->this_entry->uses;
  855.                 do 
  856.                 {
  857.                     if ( cp->proc == p ) 
  858.                     {
  859.                         free(pc);
  860.                         return(1);
  861.                     }
  862.                     if ( cp->next_ptr )
  863.                         cp = cp->next_ptr;
  864.                     else
  865.                         break;
  866.                 } while ( cp );
  867.                 cp->next_ptr = pc;
  868.             }
  869.             else stree->this_entry->uses = pc;
  870.             return(1);
  871.         }
  872.         else 
  873.         {
  874.             if(store_uses(stree->left,tindex,p) == 0)
  875.                 store_uses(stree->right,tindex,p);
  876.         }
  877.     }
  878.     return(0);
  879. }
  880.  
  881. /****************************************************************************/
  882. /* Enter tree with tindex, returns ptr to call structure */
  883. int search_call( struct tnode *stree, int tindex, struct cptr **pc )
  884. {
  885.     if ( stree ) 
  886.     {
  887.         if (stree->this_entry->index == tindex) 
  888.         {
  889.             *pc = stree->this_entry->calls;
  890.             return(1);
  891.         }
  892.         else 
  893.         {
  894.             if( search_call(stree->left,tindex,pc) == 0)
  895.                 search_call(stree->right,tindex,pc);
  896.         }
  897.     }
  898.     return(0);
  899. }
  900.  
  901. /****************************************************************************/
  902. /* Enter tree with tindex, returns ptr to uses structure */
  903. int search_use( struct tnode *stree, int tindex, struct cptr **pc )
  904. {
  905.     if ( stree ) 
  906.     {
  907.         if (stree->this_entry->index == tindex) 
  908.         {
  909.             *pc = stree->this_entry->uses;
  910.             return(1);
  911.         }
  912.         else 
  913.         {
  914.             if( search_use(stree->left,tindex,pc) == 0)
  915.                 search_use(stree->right,tindex,pc);
  916.         }
  917.     }
  918.     return(0);
  919. }
  920.  
  921. /****************************************************************************/
  922. void module_map( struct cptr *modlist[], char *title )
  923. {
  924.     register int   i,j;
  925.     struct cptr *pc,*cp;
  926.  
  927.     NewPage();
  928.     underline_on();
  929.     fprintf(TempFile,title);
  930.     underline_off();
  931.  
  932.     cp = modlist[0];
  933.     for ( i=0 ; i < nextf; i++) 
  934.     {
  935.         cp = modlist[i];
  936.         if ( cp ) 
  937.         {
  938.             fprintf(TempFile,"          %-19.19s ",fname[i]);
  939.             j = 0;
  940.             pc = cp;
  941.             while ( pc ) 
  942.             {
  943.                 if ( j > 2 ) 
  944.                 {
  945.                     j = 0;
  946.                     fprintf(TempFile,"\n                              ");
  947.                     LineNumber++;
  948.                     if ( LineNumber + 5 > PageEnd ) 
  949.                     {
  950.                         NewPage();
  951.                         underline_on();
  952.                         fprintf(TempFile,title);
  953.                         underline_off();
  954.                         fprintf(TempFile,"\n                              ");
  955.                         LineNumber++;
  956.                         j = 0;
  957.                     }
  958.                 }
  959.                 fprintf(TempFile,"%-19.19s ",fname[pc->proc]);
  960.                 j++;
  961.                 pc = pc->next_ptr;
  962.             }
  963.             fprintf(TempFile,"\n\n");
  964.             LineNumber++;
  965.             LineNumber++;
  966.         }
  967.     }
  968. }
  969.  
  970. /****************************************************************************/
  971. void  proc_map( int ( *sroutine )( struct tnode *proctree,
  972.                                     int tproc, struct cptr **pc ), char *title )
  973. {
  974.     char  ws[100];
  975.     struct cptr *pc;
  976.     register int   i,j;
  977.     int   tproc;
  978.  
  979.     NewPage();
  980.     underline_on();
  981.     fprintf(TempFile,title);
  982.     underline_off();
  983.  
  984.     i = 0;
  985.     do 
  986.     {
  987.         tproc = TocIndex[i];
  988.         if ( tproc ) 
  989.         {
  990.             searchtree_index(proctree,ws,tproc);
  991.             fprintf(TempFile,"          %-19.19s ",ws);
  992.             j = 0;
  993.             sroutine(proctree,tproc,&pc);
  994.             while ( pc ) 
  995.             {
  996.                 searchtree_index(proctree,ws,pc->proc);
  997.                 if ( j > 2 ) 
  998.                 {
  999.                     j = 0;
  1000.                     fprintf(TempFile,"\n                              ");
  1001.                     LineNumber++;
  1002.                     if ( LineNumber + 5 > PageEnd ) 
  1003.                     {
  1004.                         NewPage();
  1005.                         underline_on();
  1006.                         fprintf(TempFile,title);
  1007.                         underline_off();
  1008.                         fprintf(TempFile,"\n                              ");
  1009.                         LineNumber++;
  1010.                         j = 0;
  1011.                     }
  1012.                 }
  1013.                 fprintf(TempFile,"%-19.19s ",ws);
  1014.                 j++;
  1015.                 pc = pc->next_ptr;
  1016.             }
  1017.             fprintf(TempFile,"\n");
  1018.             LineNumber++;
  1019.         }
  1020.         else 
  1021.         {
  1022.             printf("%s", Toc[i]);
  1023.             LineNumber += 2;
  1024.         }
  1025.         if ( LineNumber + 5 > PageEnd ) 
  1026.         {
  1027.             NewPage();
  1028.             underline_on();
  1029.             fprintf(TempFile,title);
  1030.             underline_off();
  1031.             j = 0;
  1032.         }
  1033.         i++;
  1034.     } while ( i < TocCount );
  1035. }
  1036.  
  1037. /*****************************************************************************/
  1038. void DumpCrossReference( void )
  1039. {
  1040.     int   i;
  1041.  
  1042.     PageNumber = -1; 
  1043.     LineNumber = 0; 
  1044.     TempFile = stdout;         /* default output to standard out     */
  1045.  
  1046.     fprintf(stderr, "\nLinking Cross References.....");
  1047.  
  1048.     /* strip out non-module calls (maybe use these later) */
  1049.     /* build calls and uses references */
  1050.  
  1051.     for ( i = 0; i < num_call ; i++) 
  1052.     {
  1053.         proc_index = 0;
  1054.         searchtree_word(proctree,call_list[i].call,&proc_index);
  1055.         if ( proc_index ) 
  1056.         {
  1057.             store_call(proctree,call_list[i].proc);
  1058.             store_uses(proctree,proc_index,call_list[i].proc);
  1059.             store_mod_call(modcall,call_list[i].module,module_index);
  1060.             store_mod_call(moduse,module_index,call_list[i].module);
  1061.         }
  1062.     }
  1063.  
  1064.     fprintf(TempFile,"%s",printer->prt_init);
  1065.     /* complete the call list */
  1066.     /* first, do the module to module maps */
  1067.     Name = "MODULE INTERACTION MAP";
  1068.     module_map(modcall,"          Module Name         Uses These Modules:\n\n");
  1069.     module_map(moduse,"          Module Name         Is Used by These Modules:\n\n");
  1070.  
  1071.     /* dump procedure cross references */
  1072.     /* will be in order to Table of Contents */
  1073.  
  1074.     Name = "PROCEDURE CROSS REFERENCE MAP";
  1075.     proc_map(search_call,"          Procedure           Uses These Procedures:\n\n");
  1076.     proc_map(search_use,"          Procedure Name      Is Used By These Procedures:\n\n");
  1077.  
  1078.     fflush(stdout);                     /* make sure everything is written out*/
  1079.     BreakPage();
  1080. }
  1081.  
  1082. /****************************************************************************/
  1083. void Done( void )
  1084. {
  1085.     if( TempName )       /* if you created a file  */
  1086.         unlink( TempName );  /* Delete temporary file  */
  1087.     exit(0);          /* and leave the hard way */
  1088. }
  1089.  
  1090. /****************************************************************************/
  1091. /* Process Incoming File */
  1092. void List( void )
  1093. {
  1094.     register int    bp;
  1095.     char            buffer[257];
  1096.  
  1097.     if( sectionflg ) 
  1098.     {                  /* if by section             */
  1099.         PageNumber = 1;                  /* Pages start at 1          */
  1100.         LineNumber = 0;                  /* Lines reset each time     */
  1101.         BreakPage();                     /* form feed if allowed      */
  1102.     }
  1103.     NewPage();                          /* bump page & output header */
  1104.     NewFile();
  1105.     bp = Braces = 0;                    /* no begin page and braces  */
  1106.  
  1107.     while( fgets(buffer, 256, File) != NULL ) 
  1108.     {  /* read a line upto 256 bytes*/
  1109.         Rs(buffer);                               /* Remove Trailing Spaces    */
  1110.         if( bp )                                  /* if beginning page         */
  1111.             NewFunction();                         /* setup for new function    */
  1112.         if( (LineNumber + 1) > PageEnd )          /* if going past page end   */
  1113.             NewPage();                               /* start a new page         */
  1114.         if(!Braces && LooksLikeFunction(buffer))    /* no braces and a function */
  1115.         {
  1116.             AddToTableOfContents();                   /* then add to TOC          */
  1117.         }
  1118.         else
  1119.             CrossRefFunction(buffer);
  1120.  
  1121.         bp = PutLine(buffer);
  1122.         LineNumber++;
  1123.     }
  1124.     if( sectionflg )                     /* if by sections           */
  1125.         SectionNumber ++;                 /* Bump to next Section     */
  1126. }
  1127. /****************************************************************************/
  1128. /* Process New Page */
  1129. void NewPage( void )
  1130. {
  1131.     if( LineNumber > HEADER_SIZE )  
  1132.     {
  1133.         if( PageNumber >= 0 ) 
  1134.         {
  1135.             PageNumber ++;             /* bump Page Number      */
  1136.         }
  1137.         BreakPage();                  /* form feed if allowed  */
  1138.         LineNumber = 0;               /* set flag for a header */
  1139.     }
  1140.     if( LineNumber == 0 )            /* Each new page         */
  1141.         PutHeader();                  /* Outputs a Header      */
  1142. }
  1143. /****************************************************************************/
  1144. void NewFile( void )
  1145. {
  1146.     register int    i, l;
  1147.     char            temp[80];
  1148.  
  1149.     if (TocCount >= TOC_LEN) 
  1150.     {
  1151.         fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
  1152.         exit (1);
  1153.     }
  1154.  
  1155.     if( (Toc[TocCount] = (char *) malloc(130)) == NULL)   /* allocate some memory */
  1156.         ReportMemoryError();
  1157.     sprintf (Toc[TocCount], "\n\tModule: %s%s%s", printer->prt_double_width_on,Name,printer->prt_normal);
  1158.     l = strlen(Name)*3  + 6;                  /* and findout how long it is */
  1159.  
  1160.     if( l < 64 )  
  1161.     {                                 /* if not to long */
  1162.         i = (64 - l) / 8;                            /* calc. TAB increment */
  1163.         for( l=0; l < i; ++l )                       /* keep within 64 columns */
  1164.             strcat(Toc[TocCount],"\t");               /* and put some TAB's out */
  1165.     }
  1166.  
  1167.     file_stats(Name);                     
  1168.  
  1169.     if(! sectionflg ) 
  1170.     {
  1171.         sprintf (temp, "  Page %4d  (%s  %s)\n",     /* Page #, Time & date */
  1172.             PageNumber, file_date_buff, file_time_buff);
  1173.     }
  1174.     else 
  1175.     {
  1176.         sprintf (temp, "  Section %4d (%s  %s)\n",   /* Section, Time & Date*/
  1177.             SectionNumber, file_date_buff, file_time_buff);
  1178.     }
  1179.  
  1180.     strcat(Toc[TocCount], temp);              /* copy to main buffer */
  1181.     ++ TocCount;                              /* bump the entries    */
  1182.     if (NumLines)                             /* if numbering lines  */
  1183.         Number  = 1;                           /* reset linenumber    */
  1184.     InComment = InString = InXComment = InXString = 0;     /* not in comment or string */
  1185. }
  1186.  
  1187. /****************************************************************************/
  1188. int PutLine( register char   *l )
  1189. {
  1190.     register char   c;
  1191.     int             bp;
  1192.     char            *save;
  1193.     char            *section, *p;
  1194.     int             offset;
  1195.     char            Digits[15];
  1196.     int             Size;
  1197.     int             pos;
  1198.  
  1199.     bp = 0;
  1200.  
  1201.     for( save = expand(l); ( (c = *l) != 0); ++l ) 
  1202.     {  /* bump thru the string */
  1203.         if( InComment )                                /* if your in a comment  */
  1204.             l = EndComment(l,&InComment);                          /* process till your out */
  1205.         else
  1206.             if( InString )                              /* if your in a string   */
  1207.                 l = EndString(l,&InString);               /* process till your out */
  1208.             else
  1209.                 switch(c)  
  1210.                 {                             /* it must be something  */
  1211.                     case '{':                             /* curly brace IN        */
  1212.                         ++Braces;                    /* increment brace count */
  1213.                         break;
  1214.                     case '}':                             /* curly brace OUT       */
  1215.                         if( --Braces == 0)           /* coming out yet?       */
  1216.                             if (*(l+1) == ';')        /* is it structure?      */
  1217.                                 ++l;                   /* continue thru string  */
  1218.                             else
  1219.                                 if(extra_lines)        /* if option enabled    */
  1220.                                     bp = 1;             /* flag for extra lines */
  1221.                         break;
  1222.                     case '\'':                            /* Forward Slash         */
  1223.                         ++l;                         /* continue thru string  */
  1224.                         break;
  1225.                     case '"':                             /* Quotation Mark        */
  1226.                         InString = 1;                /* must be in a string   */
  1227.                         break;
  1228.                     case '/':                             /* Start of Comment      */
  1229.                         if( *(l+1) == '*' ) 
  1230.                         {        /* is next character * ? */
  1231.                             InComment = 1;            /* must be in a comment  */
  1232.                             ++l;                      /* continue thru string  */
  1233.                         }
  1234.                         break;
  1235.                 }
  1236.     }
  1237.  
  1238.     if (NumLines)  
  1239.     {                                  /* if line numbering enabled */
  1240.         sprintf (Digits,"[%4d]  ", Number);            /* make a string         */
  1241.         Size = strlen(Digits);                         /* calc. its size        */
  1242.     }
  1243.     else 
  1244.     {
  1245.         Size = 0;                                      /* else it's size is 0       */
  1246.     }
  1247.  
  1248.     if (strlen(save) +                                /* if original strings size  */
  1249.         Size  >                                 /* and the size of numbers   */
  1250.         PageWidth)  
  1251.     {                           /* are bigger than the width */
  1252.         section = substr1(save, 0, PageWidth - Size);
  1253.         if (section[strlen(section) - 1] != ' ')
  1254.             if (NULL == (p = strrchr(section, ' ')))
  1255.                 offset = strlen(section);
  1256.             else
  1257.                 offset = p - section;
  1258.         else
  1259.             offset = strlen(section) - 1;
  1260.  
  1261.         section[offset] = NULL;
  1262.  
  1263.         if (NumLines)  
  1264.         {                               /* if line numbering is enabled */
  1265.             fprintf (TempFile, "[%4d]  %s\n", Number++, section);
  1266.         }
  1267.         else  
  1268.         {
  1269.             fprintf (TempFile, "%s\n", section);
  1270.         }
  1271.  
  1272.         pos = offset + 1;
  1273.         do  
  1274.         {
  1275.             section = substr1(save, pos, pos + PageWidth - 8);
  1276.             if (strlen(save) - pos + 8 > PageWidth)
  1277.                 if (section[strlen(section) - 1] != ' ')
  1278.                     if (NULL == (p = strrchr(section, ' ')))
  1279.                         offset = strlen(section);
  1280.                     else
  1281.                         offset = p - section;
  1282.                 else
  1283.                     offset = strlen (section) - 1;
  1284.             else
  1285.                 offset = strlen(section);
  1286.  
  1287.             section[offset] = NULL;
  1288.  
  1289.             /** ----------------------------------------------------------------- **/
  1290.             /* Removed this for some reason
  1291.             /*
  1292.             /*           if (section[strlen(section) - 1] == '\n')
  1293.             /*              section[strlen(section) - 1] = NULL;
  1294.             */
  1295.  
  1296.             /*  Line is to long for pagewidth so continue on next line */
  1297.  
  1298.             fprintf (TempFile, "C       %s\n", section);
  1299.             if (++LineNumber > PageEnd)
  1300.                 NewPage();
  1301.         } while ((pos += offset + 1) < strlen(save));
  1302.     }
  1303.     else  
  1304.     {
  1305.         if (NumLines)     /* if line numbering enabled */
  1306.             fprintf (TempFile, "[%4d]  %s\n", Number++, save);
  1307.         else
  1308.             fprintf (TempFile, "%s\n", save);
  1309.     }
  1310.  
  1311.     return(bp);
  1312. }
  1313.  
  1314. /****************************************************************************/
  1315. /* Process New Function */
  1316. void NewFunction( void )              
  1317. {
  1318.     register int    i;
  1319.  
  1320.     if( LineNumber > (PageLength * 3 / 4) )       /*  49.5 lines            */
  1321.         NewPage();
  1322.     else  
  1323.     {
  1324.         if (!OnePerPage)  
  1325.         {              /* if mult. functions per page  */
  1326.             for( i=0; i < (PageLength/7); ++i )
  1327.                 putc ('\n', TempFile);      /*   add extra lines           */
  1328.             LineNumber += PageLength/7; /*   set line counter also     */
  1329.         }
  1330.         else
  1331.             NewPage();              /* otherwise its 1 func. per page*/
  1332.     }
  1333. }
  1334.  
  1335. /****************************************************************************/
  1336. /* Process Page Break */
  1337. void BreakPage( void )        
  1338. {
  1339.     if(header_flag)            /* if its allowed send a FORM FEED           */
  1340.         new_print_page();
  1341. }
  1342.  
  1343. /****************************************************************************/
  1344. void PutHeader( void )
  1345. {
  1346.     register int    i, l;
  1347.  
  1348.     putc ('\n', TempFile);
  1349.  
  1350.     if(header_flag)  
  1351.     { 
  1352.         print_double_width();
  1353.         l = strlen(Name) * 3;   
  1354.         fprintf (TempFile, "%s", Name);        /* Write out Filename or TOC */
  1355.         normal_print();
  1356.     }
  1357.     if( PageNumber > 0 ) 
  1358.     {                    /* if you're not on the TOC pages */
  1359.         for( i = (l+7)/8; i < 6; ++i )
  1360.             putc ('\t', TempFile);              /* Tab out for position         */
  1361.  
  1362.         if(! sectionflg ) 
  1363.         {
  1364.             fprintf (TempFile, "%s\tPage: %d\n\n\n", Todayv,PageNumber);
  1365.         }
  1366.         else 
  1367.         {
  1368.             fprintf (TempFile, "%s\tSection %3d - %d\n\n\n",
  1369.                 Todayv,SectionNumber,PageNumber);
  1370.         }
  1371.         if(header_lines)                       /* Header for TOP OF PAGE */
  1372.             fprintf (TempFile, "%s", header_buffer);
  1373.     }
  1374.     else 
  1375.     {                                    /* 1st line of Table of Contents page gets the time and date */
  1376.         for( i = (l+7)/8; i < 6; ++i )         /* Tab out for time/date  */
  1377.             putc ('\t', TempFile);
  1378.         fprintf (TempFile, "\n%s\n", Todayv);  /* Todays Time and Date   */
  1379.         if(header_lines)                       /* Header for TOP OF PAGE */
  1380.             fprintf (TempFile, "%s", header_buffer);
  1381.     }
  1382.     LineNumber += (HEADER_SIZE + header_lines);     /* bump line number counter */
  1383. }
  1384.  
  1385. /****************************************************************************/
  1386. int keycomp( char *elem1, char *elem2 )
  1387. {
  1388.     int   i;
  1389.  
  1390.     i = strcmp(strcompress(elem1),strcompress(elem2) );
  1391.     return(i);
  1392. }
  1393.  
  1394. /****************************************************************************/
  1395. void write_xref( char *s )
  1396. {
  1397.     if ( cproc ) 
  1398.     {
  1399.         if ( strlen( s = strcompress(s) ) ) 
  1400.         {
  1401.             if ( bsearch(s,ckeys,KEYSIZE,sizeof(ckey_type), keycomp ) == NULL ) 
  1402.             {
  1403.                 /* printf(xref,"%3d %3d %-20.20s\n",module_index,proc_index, s ); */
  1404.                 if ( num_call < MAX_XREF-1 ) 
  1405.                 {
  1406.                     call_list[num_call].module = module_index;
  1407.                     call_list[num_call].proc   = proc_index;
  1408.                     call_list[num_call].call   = strsave(s);
  1409.                     num_call++;
  1410.                 }
  1411.             }
  1412.         }
  1413.     }
  1414. }
  1415.  
  1416. /****************************************************************************/
  1417. LooksLikeFunction( char *s )
  1418. {
  1419.     char            *p;
  1420.     char            *save;
  1421.     int             nosl,nolp,norp,flg;
  1422.     int             AddOne = 0;
  1423.  
  1424.     if( InComment || InString)    /* if you're in a comment or in a string */
  1425.         return(0);                 /* just leave and return 0             */
  1426.  
  1427.     p = FunctionName;             /* assign pointer to function name string */
  1428.     save = s;                     /* save address of string                 */
  1429.  
  1430.     nosl = nolp = norp = 0;       /* no left or right paren or no slash     */
  1431.  
  1432.     flg = 1;
  1433.  
  1434.     for(; *s && flg  ; s++)  
  1435.     {    /* go until end of string or flag is set  */
  1436.         switch  (*s)  
  1437.         {            /* switch on each character in string     */
  1438.             case  '(':              /* is it a left paren?                    */
  1439.                 if (!nolp) 
  1440.                 {         /* if no left paren already               */
  1441.                     nolp = 1;         /* flag that you've got one               */
  1442.  
  1443.                     /* 3/4/87 added following line to include ARGS in TOC */
  1444.                     *p++ = *s;        /* move byte of ARG into function buffer */
  1445.                 }
  1446.                 else
  1447.                     return(0);        /* or return if you've already had one    */
  1448.                 break;
  1449.  
  1450.             case  ')':              /* is it a right paren?                   */
  1451.                 if (nolp && !norp) 
  1452.                 { /* if already a left paren and no right yet */
  1453.                     norp = 1;         /* flag that you've got a right paren     */
  1454.  
  1455.                     /* 3/4/87 added following line to include ARGS in TOC */
  1456.                     *p++ = *s;        /* move byte of ARG into function buffer  */
  1457.                 }
  1458.                 else
  1459.                     return(0);        /* or return if conditions were'nt right  */
  1460.                 break;
  1461.  
  1462.             default:                   /* everything comes thru here             */
  1463.                 if (!nolp)  
  1464.                 {           /* if no left paren yet                   */
  1465.                     if (isiechr(*s))  
  1466.                     {  /* is it alpha,digit,'_*\t\n'?        */
  1467.                         if (isidchr(*s))  /* is it alpha,digit,'_' or ' '?      */
  1468.                             *p++ = *s;     /* if it is store the byte for TOC    */
  1469.                         else            
  1470.                             p = FunctionName; /* start over if '*\t\n' & nolp */
  1471.                         break;
  1472.                     }
  1473.                     else
  1474.                         return(0);        /* return if conditions weren't right     */
  1475.                 }
  1476.  
  1477.                 if (!norp)  
  1478.                 {                       /* if no right paren yet                  */
  1479.                     if (isiechr(*s) || *s == ',') 
  1480.                     {  /* is it alpha,digit,'_ *\t\n'?*/
  1481.  
  1482.                         /* 3/4/87 added following line to include ARGS in TOC */
  1483.                         *p++ = *s;        /* move byte of ARG in function buffer    */
  1484.                         break;
  1485.                     }
  1486.                     else
  1487.                         return(0);     /* return if conditions weren't right */
  1488.                 }
  1489.  
  1490.                 if (Cmemb(*s," \t\n\r") && !nosl)   /* is it ' \t\n\r' or no slash yet */
  1491.                     break;
  1492.  
  1493.                 if (*s == '/' && !nosl)  
  1494.                 { /* is it a '/' and no slash yet   */
  1495.                     nosl = 1;            /* flag that you've got one       */
  1496.                     break;
  1497.                 }
  1498.  
  1499.                 if (*s == '*' && nosl)  
  1500.                 {  /* if its '*' & you got a slash already */
  1501.                     flg = 0;                /* set flag to abort loop         */
  1502.                     break;
  1503.                 }
  1504.                 return(0);                    /* return if conditions not right */
  1505.         }                                   /* end of switch */
  1506.     }                                      /* end of for loop */
  1507.  
  1508.     if (nolp != 1)                         /* return if no left paren found  */
  1509.         return(0);
  1510.  
  1511.     *p = '\0';                             /* else terminate function buffer */
  1512.  
  1513.     if (NumLines)  
  1514.     {                       /* if line numbering enabled      */
  1515.  
  1516.         /* the following code indents the Funtion Names with Line Numbering
  1517.             It is removed in favor of inserting a blank line */
  1518.         /***
  1519.              sprintf (Digits,"[%4d]  ", Number);        
  1520.             Cnt = strlen(Digits) + AddOne;            
  1521.              while (Cnt-- > 0)
  1522.                  putc (' ', TempFile);
  1523.              AddOne = 0;
  1524.         ***/
  1525.         putc('\n', TempFile);
  1526.         LineNumber++;
  1527.     }
  1528.     /*
  1529.      * This will cause the function name part of the line to
  1530.      * be double striken.
  1531.     */
  1532.     if( double_strike == 3) 
  1533.     {
  1534.         while (*save && *save != '(')    /* double strike up to func  name */
  1535.             putc (*save++, TempFile);
  1536.         putc ('\r', TempFile);           /* use CR for doublestrike        */
  1537.     }
  1538.     return(1);
  1539. }
  1540. /****************************************************************************/
  1541. /* Enter tree with tindex, returns with alfa string corresponding */
  1542. int searchtree_index( struct tnode *stree, char *word, int tindex )
  1543. {
  1544.     if ( stree ) 
  1545.     {
  1546.         if (stree->this_entry->index == tindex) 
  1547.         {
  1548.             strcpy(word,stree->this_entry->proc);
  1549.             module_index = stree->this_entry->module;
  1550.             return(1);
  1551.         }
  1552.         else 
  1553.         {
  1554.             if(searchtree_index(stree->left,word,tindex) == 0)
  1555.                 searchtree_index(stree->right,word,tindex);
  1556.         }
  1557.     }
  1558.     return(0);
  1559. }
  1560.  
  1561. /****************************************************************************/
  1562. /* enter with word, returns index */
  1563. int searchtree_word( struct tnode *stree, char *word, int *tindex )
  1564. {
  1565.     if( stree ) 
  1566.     {
  1567.         if (stricmp(stree->this_entry->proc,word ) == 0) 
  1568.         {
  1569.             proc_index = stree->this_entry->index;
  1570.             module_index = stree->this_entry->module; 
  1571.             *tindex = stree->this_entry->index;
  1572.             return(1);
  1573.         }
  1574.         else 
  1575.         {
  1576.             if(searchtree_word(stree->left,word,tindex) == 0)
  1577.                 searchtree_word(stree->right,word,tindex);
  1578.         }
  1579.     }
  1580.     return(0);
  1581. }
  1582.  
  1583. /****************************************************************************/
  1584. struct tnode *entertree( struct tnode *stree, char *word,
  1585.                                                         int *lindex, int *tindex )
  1586. {
  1587.     if(stree == NULL) 
  1588.     {
  1589.         stree = (struct tnode *)malloc(sizeof(struct tnode));
  1590.         stree->this_entry = (struct entrytype *)malloc(sizeof(struct entrytype));
  1591.         stree->left = NULL;
  1592.         stree->right = NULL;
  1593.         stree->this_entry->calls = NULL;
  1594.         stree->this_entry->uses = NULL;
  1595.         stree->this_entry->proc = strsave(word);
  1596.         stree->this_entry->module = module_index;
  1597.         (*lindex)++;
  1598.         stree->this_entry->index = *lindex;
  1599.         *tindex = *lindex;
  1600.     }
  1601.     else
  1602.         switch(strcmp(stree->this_entry->proc,word)) 
  1603.         {
  1604.             case 0:
  1605.                 *tindex = stree->this_entry->index;
  1606.                 break;
  1607.             case 1:
  1608.                 stree->left = entertree(stree->left,word,lindex,tindex);
  1609.                 break;
  1610.             default:
  1611.                 stree->right = entertree(stree->right,word,lindex,tindex);
  1612.         }
  1613.     return(stree);
  1614. }
  1615.  
  1616. /****************************************************************************/
  1617. void AddToTableOfContents( void )
  1618. {
  1619.     register int    l;
  1620.     register char   *p;
  1621.  
  1622.     if (TocCount >= TOC_LEN) 
  1623.     {
  1624.         fprintf (stderr, "%s: too many table of contents entries\n", ProgName);
  1625.         exit (1);
  1626.     }
  1627.     l = strlen(FunctionName);             
  1628.     p = Toc[TocCount] = (char *) malloc(l+1);
  1629.     if( p == NULL) 
  1630.         ReportMemoryError();        
  1631.     strcpy(p, FunctionName);         
  1632.     TocPages[TocCount] = PageNumber;
  1633.     /* build a tree of procedure names and modules */
  1634.     if ( cproc ) free(cproc);
  1635.     cproc = strsave(root_name(FunctionName) );
  1636.     if ( p = strchr(cproc,'(') ) 
  1637.     {
  1638.         *p = ' ';
  1639.         while ( *p && *p != ')' ) *p++ = ' ';
  1640.         if ( *p == ')' ) *p = ' ';
  1641.     }
  1642.     cproc = strcompress(cproc);
  1643.     proctree = entertree(proctree,cproc,&last_proc_index,&proc_index);
  1644.     TocIndex[TocCount] = proc_index;
  1645.     TocCount++;
  1646. }
  1647.  
  1648. /****************************************************************************/
  1649. void DumpTableOfContents( void )
  1650. {
  1651.     register int    i, j, l;
  1652.     char  *rn;
  1653.  
  1654.     if( TocCount == 0 )              /* if there nothing to print */
  1655.         return;                       /* then just return          */
  1656.  
  1657.     if (WantSorted)                  /* if you wanted it sorted by page number */
  1658.         SortTableOfContents();        /* then we must sort it first         */
  1659.  
  1660.     Name = "TABLE of CONTENTS";      /* give me a title for the page       */
  1661.  
  1662.     PageNumber = -1;                 /* Table of Contents pages are not numbered */
  1663.     LineNumber = 0;                  /* and neither are the lines          */
  1664.     TempFile = stdout;               /* default output to standard out     */
  1665.  
  1666.     fprintf(TempFile,"%s",printer->prt_init);
  1667.     NewPage();                       /* start out creating a new page      */
  1668.  
  1669.     for( i=0; i < TocCount; ++i ) 
  1670.     {
  1671.         if( Toc[i][0] == '\n' ) 
  1672.         {
  1673.             if( (LineNumber + 5) > PageEnd )
  1674.                 NewPage();
  1675.             printf("%s", Toc[i]);
  1676.             LineNumber += 2;
  1677.             continue;
  1678.         }
  1679.         if( ++LineNumber > PageEnd )     /* if going off end of page           */
  1680.             NewPage();                    /* start a new page                   */
  1681.         rn = root_name(Toc[i]);
  1682.         l = ( (rn - Toc[i]) < 20 ) ? 20-(rn-Toc[i]) : 0;
  1683.         for ( j = 0; j < l ; j++) putchar(' ');
  1684.         printf("%s ",Toc[i]);
  1685.         l += strlen(Toc[i]);             /* length if function name with parms */
  1686.         for( j=l; j < 68; ++j )          /* put dots out to column 68          */
  1687.             putchar('.');                 /* put dots out to page num. in TOC   */
  1688.         printf(" %d\n", TocPages[i]);    /* print page number for function */
  1689.     }
  1690.     fflush(stdout);                     /* make sure everything is written out*/
  1691.     BreakPage();
  1692. }
  1693.  
  1694. /*********************************************************/
  1695. /*    Search the Table of Contents Entry and return a    */
  1696. /*    pointer to the root name part of the entry (v3.2)  */
  1697. /*********************************************************/
  1698. char *root_name( char *ns )
  1699. {
  1700.     char *p;
  1701.  
  1702.     p = ns;
  1703.     do 
  1704.     {
  1705.         p++;
  1706.     } while ( ( *p != '(' ) && ( *p ) );
  1707.     if ( *p  ) 
  1708.     {
  1709.         do 
  1710.         {
  1711.             p--;
  1712.         } while ( ( !isnamechr(*p) ) && ( p > ns) );
  1713.         do 
  1714.         {
  1715.             p--;
  1716.         } while ( ( *p != ' ' ) && ( p > ns) );
  1717.     }
  1718.     if ( *p == ' ') p++;
  1719.     if ( *p == '*') p++;
  1720.     return( p );
  1721. }
  1722.  
  1723. /****************************************************************************/
  1724. /* Sort Table of Contents by Funtion Name */
  1725. void SortTableOfContents( void )
  1726. {
  1727.     register int    i, tempint;
  1728.     char         *tempchar;
  1729.     int          flag;
  1730.  
  1731.     fprintf(stderr, "\nSorting Table of Contents.....");
  1732.     do 
  1733.     {
  1734.         flag = 0;            /* default to already sorted */
  1735.  
  1736.         for (i = 0; i < TocCount - 1; i++) 
  1737.         {   /* look at them all */
  1738.             if (Toc[i][0] == '\n' || Toc[i+1][0] == '\n')
  1739.                 continue;       /* don't sort across file names */
  1740.  
  1741.             if (stricmp (root_name(Toc[i]), root_name(Toc[i+1])) > 0) 
  1742.             {/* compare the strings        */
  1743.                 tempchar = Toc[i];            /* copy to temp pointer       */
  1744.                 Toc[i] = Toc[i+1];            /* swap the pointers in array */
  1745.                 Toc[i+1] = tempchar;       /* put the temp pointer back  */
  1746.                 tempint = TocPages[i];        /* grab the page number       */
  1747.                 TocPages[i] = TocPages[i+1];  /* swap page numbers          */
  1748.                 TocPages[i+1] = tempint;      /* put the temp page number back */
  1749.                 tempint = TocIndex[i];
  1750.                 TocIndex[i] = TocIndex[i+1];
  1751.                 TocIndex[i+1] = tempint;
  1752.                 flag = 1;                  /* indicate you've swapped    */
  1753.             }
  1754.         }
  1755.     }
  1756.     while (flag);        /* go until no more swaps can be made */
  1757. }
  1758. /****************************************************************************/
  1759. /* Process string until you come out of COMMENT */
  1760. char *EndComment( char *p, int *flag )
  1761. {
  1762.     char   c;
  1763.  
  1764.     while( (c = *p++) )          /* while there are chars to look at */
  1765.         if( c == '*' && *p == '/' ) 
  1766.         {  /* and there a splat or a slash     */
  1767.             *flag = 0;              /* say your not in the comment      */
  1768.             break;                      /* and leave the loop               */
  1769.         }
  1770.     return(p-1);                      /* returning the new pointer addr.  */
  1771. }
  1772.  
  1773. /****************************************************************************/
  1774. /* Process string until you come out of STRING  */
  1775. char *EndString( char *p, int *flag )
  1776. {
  1777.     register char   c;
  1778.  
  1779.     while( (c = *p++) != 0 )         /* while there are chars to look at */
  1780.         if( c == '\\' ) 
  1781.         {             /* and forward slashs for next line */
  1782.             continue;                  /* means "Just read on McDuck"      */
  1783.         }
  1784.         else if( c == '"' ) 
  1785.         {         /* if you found the ending quote    */
  1786.             *flag = 0;                  /* say your not in a string anymore */
  1787.             break;                     /* and leave the loop               */
  1788.         }
  1789.     return(p-1);                     /* returning the new pointer addr.  */
  1790. }
  1791. /****************************************************************************/
  1792. /*
  1793.  *      This is the function substr1().  The calling sequence is:
  1794.  *
  1795.  *                      substr1(string, startpos, endpos).
  1796.  *
  1797.  *      The function returns a pointer to a static string (written over -
  1798.  *      on subsequent calls) which is a substring of the string `string'
  1799.  *      starting at `startpos' (the first position is 0 (zero)) and ending
  1800.  *      at `endpos' (non-inclusive).  All arguments must be present or
  1801.  *      strange things happen with the system stack.
  1802.  *
  1803.  *      An example of the use is:
  1804.  *
  1805.  *              x = substr1(string, 2, 5);
  1806.  *              (where string == "This is a test.")
  1807.  *
  1808.  *      This call returns a pointer to:
  1809.  *              "is "
  1810.  *      An error code of -1 is returned is the `endpos' is greater than
  1811.  *      `startpos'
  1812.  *
  1813.  *                                              Lance E. Shepard
  1814.  */
  1815. char *substr1( char *string, int start, int end )
  1816. {
  1817.     static char  retstr[MAX_S];
  1818.     int loop1;
  1819.     int loop2;
  1820.  
  1821.     if (end < start)  
  1822.     {
  1823.         exit(-1);
  1824.     }
  1825.  
  1826.     for (loop2 = 0; loop2 < MAX_S; loop2++)
  1827.         retstr[loop2] = NULL;
  1828.  
  1829.     for (loop1 = start, loop2 = 0; string[loop1] != NULL &&
  1830.         loop1 < end && loop2 <= MAX_S; loop1++, loop2++)
  1831.         retstr[loop2] = string[loop1];
  1832.  
  1833.     retstr[++loop2] = NULL;
  1834.     return(retstr);
  1835. }
  1836.  
  1837. /****************************************************************************/
  1838. /*
  1839.  *      This is the function `char *expand().'  This function takes as
  1840.  *      an argument a NULL terminated string and replaces all occurances
  1841.  *      of the tab character with 8 (eight) spaces.  The function returns
  1842.  *      a pointer to a static string which is overwritten on subsequent
  1843.  *      calls.
  1844. */
  1845. /****************************************************************************/
  1846. char *expand( char *string )
  1847. {
  1848.     int count;
  1849.     static char retstr[MAX_S];
  1850.  
  1851.     for (count = 0; count < MAX_S; retstr[count++] = NULL);
  1852.  
  1853.     for (count = 0; *string != NULL; count++, string++)  
  1854.     {
  1855.         if (*string == '\t')  
  1856.         {
  1857.             retstr[count] = ' ';
  1858.             /*        while (((count + 1) % 8) != 0)     */
  1859.             while (TabDef[count] != 'T')
  1860.                 retstr[++count] = ' ';
  1861.         }
  1862.         else
  1863.             retstr[count] = *string;
  1864.     }
  1865.     retstr[count] = NULL;
  1866.     return(retstr);
  1867. }
  1868.  
  1869. /****************************************************************************/
  1870. /* strip trailing blanks from string  */
  1871. char *Rs( char s[] )
  1872. {
  1873.     int n;
  1874.     for (n=strlen(s)-1 ; n >= 0 && isspace(s[n]) ; n--)
  1875.         ;           /* find the last space in the string */
  1876.     s[n+1] = '\0';    /* plop a null char on top of it     */
  1877.     return(s);        /* return pointer to string          */
  1878. }
  1879.  
  1880. /****************************************************************************/
  1881. /*  is character "a" a member of string "b"  */
  1882. int Cmemb( char a, char *b )
  1883. {
  1884.     while  (*b)          /* go until the null character */
  1885.         if (a == *b++)    /* looking for the character and bumping the pointer */
  1886.             return(1);     /* returning 1 if its found */
  1887.     return( (!a) ? 1 : 0 ); /* return 0 if "a" was a non-zero character */
  1888. }
  1889.  
  1890. /****************************************************************************/
  1891. int StarDot( char *file_string )
  1892. {
  1893.     unsigned long int total_file_size = 0;
  1894.     unsigned long int total_disk_free = 0;
  1895.     int done;
  1896.     int i = 0;
  1897.  
  1898.     file_string += 2;                       /* bump past -A switch */
  1899.  
  1900.     if( (done = FindFirst(file_string,0,&fblock)) != 0) 
  1901.     {/* Attempt 1st file read */
  1902.         fprintf(stderr,"No Files Found\n");
  1903.         exit(1);
  1904.     }
  1905.     while(!done && i < N_FILES) 
  1906.     {            /* go until done or to many files */
  1907.         /*filenames[i] = strsave(fblock.name);*/
  1908.         /*strcpy(&filenames[i][0],fblock.name);*/ /* copy names into array  */
  1909.         fname[i] = strsave(fblock.name);
  1910.         i++;
  1911.         total_file_size += fblock.size;       /* keep running total of filesizes */
  1912.  
  1913.         done = FindNext(&fblock);        /* read next availables file info  */
  1914.     }
  1915.     FindClose( );
  1916.     if( i == N_FILES)
  1917.         fprintf(stderr,"Printing ONLY 1st %d Files\n", N_FILES);
  1918.  
  1919.     GetDiskFree(0, &disk_space);            /* find free disk space */
  1920.     total_disk_free = (  ((long)disk_space.bytes_per_sector  *  /* convert to bytes */
  1921.         (long)disk_space.sectors_per_cluster) *
  1922.         (long)disk_space.avail_clusters);
  1923.  
  1924.     if((total_file_size * 2) >= total_disk_free) 
  1925.     {
  1926.         fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
  1927.                    \nYou Have %lu bytes free\n",
  1928.             total_file_size * 2, total_disk_free);
  1929.         exit(1);
  1930.     }
  1931.     return(i);        /* return new number of files */
  1932. }
  1933.  
  1934. /****************************************************************************/
  1935. void ReportMemoryError( void )
  1936. {
  1937.     fprintf(stderr,"Memory Allocation Error\n");
  1938.  
  1939.     if( TempName ) 
  1940.     {        /* if there is a file to work on */
  1941.         EndTempFile();       /* Make sure file is closed */
  1942.         unlink( TempName );     /* Delete temporary file */
  1943.     }
  1944.     exit(1);
  1945. }
  1946.  
  1947. /****************************************************************************/
  1948. void ReadHeaderFile( char *header_file )
  1949. {
  1950.     extern char    header_buffer[MAX_HDR_BYTES];
  1951.     extern int     header_lines;
  1952.     int ch;
  1953.     int i = 0;
  1954.     int x = 0;
  1955.     char *string;
  1956.  
  1957.     header_file += 2;              /* strip the "-h" from the string */
  1958.     if(( Hfile = fopen(header_file, "r")) == NULL) 
  1959.     {
  1960.         fprintf(stderr,"Can't Open Header File %s\n",header_file);
  1961.         exit(1);      
  1962.     }
  1963.     else 
  1964.     {
  1965.         /* read entire file that is up to MAX_HDR_BYTES characters long */
  1966.         while( (ch = fgetc(Hfile)) != EOF) 
  1967.         {
  1968.             header_buffer[i++] = (unsigned char) ch;
  1969.             if(i < MAX_HDR_BYTES)
  1970.                 continue;
  1971.             else
  1972.                 break;
  1973.         }
  1974.         header_buffer[i] = '\0';      /* terminate buffer */
  1975.  
  1976.         fclose(Hfile);                /* and close the file */
  1977.  
  1978.         for(x = 0, string = header_buffer; x <= i; x++) 
  1979.         {
  1980.             if(*string++ == '\n')      /* count number of line feeds */
  1981.                 header_lines++;         /* tell the NewPage Function  */
  1982.         }  
  1983.     }
  1984. }
  1985.  
  1986. /****************************************************************************/
  1987. ReadResponseFile( char *response_file )
  1988. {
  1989.     char fpntr[80];            /* area for string to be read into */
  1990.  
  1991.     unsigned long int total_file_size = 0;
  1992.     unsigned long int total_disk_free = 0;
  1993.  
  1994.     int i = 0;
  1995.  
  1996.     response_file += 2;                  /* strip the "-@" from the string */
  1997.     if(( Rfile = fopen(response_file, "r")) == NULL) 
  1998.     {
  1999.         fprintf(stderr,"Can't Open Response File %s\n",response_file);
  2000.         exit(1);       /* terminate abruptly */
  2001.     }
  2002.     else 
  2003.     {
  2004.         /* read a entire line from the Rfile that is up to 80 characters long */
  2005.         while(fgets(fpntr,80,Rfile) != NULL && i < N_FILES) 
  2006.         {
  2007.             /*strtok(fpntr," \n");  */        /* strip to LF or space */
  2008.             fname[i] = strsave( strtok(fpntr," \n") );
  2009.             /*strcpy(&filenames[i][0],fpntr); */    /* copy names into array */
  2010.             /*fname[i] = filenames[i]; */     /* copy pointer to name */
  2011.             i++;
  2012.  
  2013.             FindFirst(fpntr,0,&fblock);       /* read file size in */
  2014.  
  2015.             total_file_size += fblock.size;  /* keep running total of filesizes */
  2016.         }
  2017.         fclose(Rfile);    /* and close the file */
  2018.  
  2019.         GetDiskFree(0, &disk_space);      /* find free disk space */
  2020.         total_disk_free = (  ((long)disk_space.bytes_per_sector  *  /* convert to bytes */
  2021.             (long)disk_space.sectors_per_cluster) *
  2022.             (long)disk_space.avail_clusters);
  2023.  
  2024.         if((total_file_size * 2) >= total_disk_free) 
  2025.         {
  2026.             fprintf(stderr,"Insufficient Disk Space!\nMinimum of %lu bytes needed.\
  2027.                       \nYou Have %lu bytes free\n",
  2028.                 total_file_size * 2, total_disk_free);
  2029.             exit(1);
  2030.         }
  2031.         return(i);        /* return new number of files */
  2032.     }
  2033.     return(0);
  2034. }
  2035.  
  2036. /*****************************************************************************
  2037.      This routine is executed when the CONTROL-BREAK key combination is hit
  2038.      { Not in Version 3.2 with Microsoft v5.1 but left in for others}
  2039. *****************************************************************************/
  2040. int c_break( void )
  2041. {
  2042.     fprintf(stderr,"Control-Break hit.  Program aborting ...\n");
  2043.  
  2044.     if( TempName ) 
  2045.     {           /* if you created a file    */
  2046.         EndTempFile();          /* Make sure file is closed */
  2047.         unlink( TempName );     /* Delete temporary file    */
  2048.     }
  2049.     return(0);                 /* ABORT sequence           */
  2050. }
  2051.  
  2052. /****************************************************************************/
  2053. void file_stats( char *filename )
  2054. {
  2055.     extern struct find_t fblock;
  2056.  
  2057.     FindFirst(filename,0,&fblock);    /* read data into structure     */
  2058.  
  2059.     /* ------------------- Show date in standard format --------------------*/
  2060.  
  2061.     sprintf(file_date_buff,"%02d-%02d-%02d",
  2062.         ((fblock.wr_date >> 5) & 0x0f),   /* month     */
  2063.         (fblock.wr_date & 0x1f)       ,   /* day       */
  2064.         ((fblock.wr_date >> 9) + 80  ));  /* year      */
  2065.  
  2066.     /* -----------------   Show time in 12 Hour Format   ------------------- */
  2067.     if ( (fblock.wr_time >> 0x0b) <= 12)
  2068.     {
  2069.         sprintf(file_time_buff,"%02d:%02d",
  2070.             (fblock.wr_time >> 0x0b),
  2071.             ((fblock.wr_time >> 5 ) & 0x3f ));  /* minutes   */
  2072.     }
  2073.     else
  2074.     {
  2075.         sprintf(file_time_buff,"%02d:%02d",
  2076.             ((fblock.wr_time >> 0x0b) - 12),
  2077.             ((fblock.wr_time >> 5 ) & 0x3f ));  /* minutes   */
  2078.     }
  2079.     /* ------------------     Decipher whether its AM or PM  ---------------- */
  2080.     if ( (fblock.wr_time >> 0x0b) < 12)
  2081.         strcat(file_time_buff," am"); /* for AM */
  2082.     else
  2083.         strcat(file_time_buff," pm"); /* for PM */
  2084. }
  2085.  
  2086. /****************************************************************************/
  2087. /* routine to initialize and select printer codes - called from initialize */
  2088. int printer_code_init( void )
  2089. {
  2090.     printer = &(print_code[nprinter]);
  2091.     return(1);
  2092. }
  2093.  
  2094. /****************************************************************************/
  2095. void normal_print( void )
  2096. {
  2097.     fprintf(TempFile,"%s",printer->prt_normal);
  2098. }
  2099.  
  2100. /****************************************************************************/
  2101. void emphasized_print_on( void )
  2102. {
  2103.     fprintf(TempFile,"%s",printer->prt_emphasize_on);
  2104. }
  2105.  
  2106. /****************************************************************************/
  2107. void emphasized_print_off( void )
  2108. {
  2109.     fprintf(TempFile,"%s",printer->prt_emphasize_off);
  2110. }
  2111.  
  2112. /****************************************************************************/
  2113. void print_double_width( void )
  2114. {
  2115.     fprintf(TempFile,"%s",printer->prt_double_width_on);
  2116. }
  2117.  
  2118. /****************************************************************************/
  2119. void compressed_print( void )
  2120. {
  2121.     fprintf(TempFile,"%s",printer->prt_compress);
  2122. }
  2123.  
  2124. /****************************************************************************/
  2125. void new_print_page( void )
  2126. {
  2127.     fprintf(TempFile,"%s",printer->prt_new_page);
  2128. }
  2129.  
  2130. /****************************************************************************/
  2131. void underline_on( void )
  2132. {
  2133.     fprintf(TempFile,"%s",printer->prt_underline_on);
  2134. }
  2135.  
  2136. /****************************************************************************/
  2137. void underline_off( void )
  2138. {
  2139.     fprintf(TempFile,"%s",printer->prt_underline_off);
  2140. }
  2141.  
  2142. /****************************************************************************/
  2143. void pspace( int ns )
  2144. {
  2145.     register int   i;
  2146.  
  2147.     for (i=0; i<ns; i++) fprintf(TempFile," ");
  2148. }
  2149.  
  2150. /****************************************************************************/
  2151. char *strupper( char *str )
  2152. {
  2153.     register int c;
  2154.     register char *s = str;
  2155.  
  2156.     while (c = *s)
  2157.         *s++ = (char)toupper(c);
  2158.     return(str);
  2159. }
  2160.  
  2161. /****************************************************************************/
  2162. char *strsave( char *s )
  2163. {
  2164.     char *p;
  2165.  
  2166.     if ((p=(char *)malloc(strlen(s)+1)) != NULL)
  2167.         strcpy(p,s);
  2168.     return(p);
  2169. }
  2170.  
  2171. /****************************************************************************/
  2172. void strfree( char *s )
  2173. {
  2174.     free( s );
  2175. }
  2176.  
  2177. /****************************************************************************/
  2178. /* utility to strip leading and trailing blanks */
  2179. /* from a null terminated string */
  2180. char *strcompress( char *str )
  2181. {
  2182.     register char *s;
  2183.  
  2184.     s = str + strlen(str);
  2185.     *s--;
  2186.     while ( *s == ' ' ) s--;
  2187.     *++s = '\0';
  2188.     while ( *str == ' ' ) str++;
  2189.     return(str);
  2190. }
  2191.  
  2192. /****************************************************************************/
  2193. int CrossRefFunction( char *s )
  2194. {
  2195.     char  *p,c;
  2196.     char  refname[100];
  2197.  
  2198.  
  2199.     p = refname;             /* assign pointer to function name string */
  2200.     for(; *s ; s++)  
  2201.     {
  2202.         if( InXComment )  s = EndComment(s,&InXComment);
  2203.         if( InXString ) s = EndString(s,&InXString);
  2204.         switch  (*s)  
  2205.         {
  2206.             case '\'':  while ( (c=*(++s) ) && c != '\'') ;
  2207.                 if ( *(s+1) == '\'') s++;  /* special case */
  2208.                 break;
  2209.  
  2210.             case '"':   InXString = 1;
  2211.                 while( (c = *(++s) ) && c != '\"' ) ;
  2212.                 if ( c == '\"') InXString = 0;
  2213.                 break;
  2214.             case '/':
  2215.                 if( *(s+1) == '*' ) 
  2216.                 {
  2217.                     InXComment = 1;
  2218.                     s++;
  2219.                     /***
  2220.                     while( (c = *s++) ) {
  2221.                         if( c == '*' && *s == '/' ) {
  2222.                             InXComment = 0;
  2223.                             break;
  2224.                             }
  2225.                         }
  2226.                     s--;
  2227.                     ***/
  2228.                 }
  2229.                 break;
  2230.             case  '(':
  2231.                 *p = '\0';
  2232.                 write_xref(refname);
  2233.                 p = refname;
  2234.                 break;
  2235.             case '|':
  2236.             case '^':
  2237.             case '!':
  2238.             case '.':
  2239.             case '+':
  2240.             case '-':
  2241.             case '%':
  2242.             case '*':
  2243.             case '&':
  2244.             case '?':
  2245.             case '[':
  2246.             case ']':
  2247.             case '<':
  2248.             case '>':
  2249.             case ';':
  2250.             case ':':
  2251.             case '=':
  2252.             case ',':
  2253.             case ')':     /* start name over */
  2254.                 p = refname;
  2255.                 break;
  2256.  
  2257.             default:
  2258.                 if (isiechr(*s))  
  2259.                 {  /* is it alpha,digit,'_*\t\n'?        */
  2260.                     if (isidchr(*s))  /* is it alpha,digit,'_' or ' '?      */
  2261.                         *p++ = *s;     /* if it is store the byte for TOC    */
  2262.                     else
  2263.                         p = refname; /* start over if '*\t\n' & nolp */
  2264.                     break;
  2265.                 }
  2266.         }                                   /* end of switch */
  2267.     }                                      /* end of for loop */
  2268.     return(1);
  2269. }
  2270.  
  2271. int FindFirst( char *filename, unsigned attr, struct find_t *finfo )
  2272. {
  2273. #ifndef OS2
  2274.    return( _dos_findfirst( filename, attr, finfo ) );
  2275. #else
  2276.     USHORT      nCount  = 1 ;
  2277.  
  2278.    hDir = HDIR_CREATE;
  2279.  
  2280.     _doserrno = DosFindFirst ( filename, &hDir, attr ,&FileInfo,
  2281.                               sizeof(FileInfo), &nCount, 0L) ;
  2282.    if ( nCount == 1 )
  2283.    {
  2284.       strcpy( finfo->name, FileInfo.achName );
  2285.       finfo->attrib = FileInfo.attrFile;
  2286.       finfo->size   = FileInfo.cbFile;
  2287.         memcpy( &finfo->wr_date, &FileInfo.fdateLastWrite,
  2288.                                                 sizeof( finfo->wr_date ) );
  2289.         memcpy( &finfo->wr_time, &FileInfo.ftimeLastWrite,
  2290.                                                 sizeof( finfo->wr_time ) );
  2291.    }
  2292.     return( (nCount) ? 0 : -1 );
  2293. #endif
  2294. }
  2295.  
  2296. int FindNext( struct find_t *finfo )
  2297. {
  2298. #ifndef OS2
  2299.    return( _dos_findnext( finfo ) );
  2300. #else
  2301.    USHORT      nCount  = 1 ;
  2302.  
  2303.     _doserrno = DosFindNext(hDir, &FileInfo, sizeof(FileInfo), &nCount);
  2304.    if ( nCount == 1 )
  2305.    {
  2306.       strcpy( finfo->name, FileInfo.achName );
  2307.       finfo->attrib = FileInfo.attrFile;
  2308.       finfo->size   = FileInfo.cbFile;
  2309.         memcpy( &finfo->wr_date, &FileInfo.fdateLastWrite,
  2310.                                                 sizeof( finfo->wr_date ) );
  2311.         memcpy( &finfo->wr_time, &FileInfo.ftimeLastWrite,
  2312.                                                 sizeof( finfo->wr_time ) );
  2313.    }
  2314.     return( (nCount) ? 0 : -1 );
  2315. #endif
  2316. }
  2317.  
  2318. int FindClose( void )
  2319. {
  2320. #ifndef OS2
  2321.    return( 0 );
  2322. #else
  2323.     return( DosFindClose( hDir ) );
  2324. #endif
  2325. }
  2326.  
  2327. int GetDiskFree( unsigned drive, struct diskfree_t *disk_space )
  2328. {
  2329.     int    rc;
  2330.  
  2331. #ifndef OS2
  2332.     rc = _dos_getdiskfree( drive, disk_space );
  2333. #else
  2334.     USHORT        usDrv;
  2335.     FSALLOCATE    FileInfo;
  2336.  
  2337.     usDrv = drive & 0x1F;
  2338.  
  2339.     rc = DosQFSInfo( usDrv, 1, ( PBYTE )&FileInfo, sizeof( FileInfo ) );
  2340.  
  2341.     switch ( rc )
  2342.     {
  2343.         case NO_ERROR :
  2344.             disk_space->total_clusters = FileInfo.cUnit;
  2345.             disk_space->avail_clusters = FileInfo.cUnitAvail;
  2346.             disk_space->sectors_per_cluster = FileInfo.cSectorUnit;
  2347.             disk_space->bytes_per_sector = FileInfo.cbSector;
  2348.             rc = 0;
  2349.             break;
  2350.         default:
  2351.             rc = -1;        /* set default return code */
  2352.             break;
  2353.     }
  2354. #endif
  2355.     return( rc );
  2356. }
  2357.  
  2358.