home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 364_01 / intf_ca.c < prev    next >
C/C++ Source or Header  |  1992-05-26  |  19KB  |  787 lines

  1. /*
  2. HEADER:         ;
  3. TITLE:          C-ACROSS;
  4. VERSION         1.02
  5.  
  6. DESCRIPTION:   "Utility for multiple module programs. Produces
  7.       Six indexes of functions, prototypes, and globals that
  8.       enable user to 'see across' modules for use in checking
  9.       and comparison.  One of these is type of hierarchical
  10.       functions list, a listing by module of functions
  11.       and calls made FROM them; another is alphabetical list
  12.       of functions and calls made TO them. Globals listed
  13.       in schematic descriptors which record all modifiers
  14.       and qualifiers and enable checking of declarators
  15.       across modules. Creates, on request, header file
  16.       consisting of prototypes constructed from function
  17.       definitions. Can list user types #defined and some
  18.       preprocessor #defines. Full documentation in README.CA";
  19.  
  20. KEYWORDS:       Utility, Cross Reference, Deubgging;
  21. SYSTEM:         MS-DOS;
  22. FILENAME:       INTF_CA.C;
  23.  
  24. WARNINGS:      "1. Assumes function definitions conform with
  25.         ANSI standards and have prototype form. See
  26.         also "Caveats and Restrictions" in README.CA.
  27.         2. Assumes syntactically correct source files.
  28.         3. Written and tested using Microsoft QuickC.
  29.         4. Copyright retained.  See Copyright
  30.         information in README.CA.";
  31.  
  32. SEE-ALSO:      EXIT_CA.C, FUNC_CA.C, GLOB_CA.C, IFDEF_CA.C, INTF_CA.C,
  33.            LINKL_CA.C, PARSE_CA.C, TDEF_CA.C, TYPES_CA, UTIL_CA.C,
  34.            UTLG_CA.C, XRF_CA.C, README.CA,
  35.            CA.H, CA.PRJ, CA.RPT, CDECL_CA.H, KEYWORDS.H;
  36. AUTHORS:       Myron Turner;
  37. COMPILERS:     Microsoft C;
  38.  
  39. */
  40.  
  41. /***************************  C-ACROSS  ***************************
  42.                    V. 1.02
  43.                Copyright (C) Myron Turner
  44.  
  45.               333 Bartlet Ave.
  46.               Winnipeg, Manitoba
  47.               Canada R3L 0Z9
  48.               (204) 284-8387
  49.  
  50. *********************************************************************/
  51.  
  52.  
  53. #include <stdio.h>
  54. #include <string.h>
  55. #include <graph.h>
  56. #include <malloc.h>
  57. #include <stdlib.h>
  58. #include <conio.h>
  59. #include <dos.h>
  60. #include <direct.h>
  61. #include <errno.h>
  62. #define EXIT_CODES
  63. #include "ca.h"
  64. #include "ca_decl.h"
  65.  
  66. #define WHITE   0x7
  67. #define INTENSE 0x8
  68. #define HIGH_VIDEO  _settextcolor(WHITE | INTENSE)
  69. #define LOW_VIDEO   _settextcolor(WHITE)
  70.  
  71. /* general externs and globals */
  72. extern struct globals_list *globals_start;
  73. char rpt_fname[_MAX_FNAME] = "\0\0";
  74. char *CurrentMod = NULL;
  75. struct rccoord locate;
  76.  
  77. /* Globals for Command Line Options */
  78. int __Inclf_Limit = 5;
  79. char NewInclude[128]="INCLUDE=\0\0";
  80. FILE *scrn_out = (FILE *)stdout;
  81. int declare_file = 0;
  82. int user_hf_VAR = 0;
  83. int user_hf_FUNC = 0;
  84. int user_hfile_only = 0;
  85. int verbose = 0;
  86. size_t GLfpSsize = 15;
  87. static SplitNumber_rpf = 0;
  88.  
  89. int IfDefOFF = 0;
  90. int __Complex_Declarators = 1;
  91. int __Complex_Prototypes = 1;
  92.  
  93. void ini_characterset(void);
  94.  
  95. /** NOTE: Command Line and Makefile filespecs are limited to 63 characters**/
  96. /**This is set by FILENAME_MAX in STDIO.H**/
  97.  
  98. int switches_found = 0;
  99. void main(int argc, char **argv)
  100. {
  101.  struct filespec *c_file_start = NULL;
  102.  struct func *func_start;
  103.  FILE *rptfp;
  104.  char *file_string =  NULL;
  105.  int prj = 0;
  106.  
  107.  _clearscreen(0);
  108.  if (argc > 1) {
  109.     file_string = argv_cat(argc, argv);
  110.     if (*file_string == '@')   {
  111.      prj = 1;
  112.      file_string = readmakefile(file_string);
  113.      }
  114.     if (file_string)
  115.       c_file_start = extract_file_names(file_string);
  116.       else {
  117.     int c;
  118.     printf("\nMake file not found. Continue [Y/N]?\n");
  119.     c = getch();
  120.     if (c != 'y' || c != 'Y') exit(0);
  121.     }
  122.     }
  123.  if (!file_string || (!c_file_start && switches_found))
  124.                c_file_start = get_modules();
  125.  if (!c_file_start)
  126.       if (file_string && prj) exit_ca (BAD_PROJ, "");
  127.  if (!c_file_start) exit_ca (NO_FILE_STR, "");
  128.  rptfp = make_rptfile(c_file_start->path);
  129.  
  130.  ini_characterset();
  131.  
  132.  loop_through_modules (c_file_start, &func_start, rptfp);
  133.  if (declare_file) { fcloseall(); exit(0); }
  134.  
  135.  print_ll(func_start, rptfp);
  136.  
  137.  if(SplitNumber_rpf == 3)
  138.    rptfp = open_reportfile(FIRST_SPLIT);
  139.  
  140.  xrf(func_start, c_file_start, rptfp);
  141.  
  142.  if(SplitNumber_rpf == 2)
  143.    rptfp = open_reportfile(FIRST_SPLIT);
  144.  
  145.  print_calls_from(func_start, rptfp);
  146.  print_fnptrs(func_start,rptfp);
  147.  
  148.  if(SplitNumber_rpf == 3)
  149.       rptfp = open_reportfile(SECOND_SPLIT);
  150.  
  151.  print_alphab_globals(globals_start, rptfp);
  152.  
  153.  fcloseall();
  154.  
  155. }
  156.  
  157. /*lint -epu */
  158.  
  159. struct filespec *get_modules(void)
  160. {
  161.  
  162.   char *file_string, buffer[81];
  163.   size_t strL;
  164.   int ampersand;
  165.  
  166.  instructions();
  167.  
  168.  if ( !( file_string = (char *) malloc(sizeof (char) * 81 ) ) )return NULL;
  169.  
  170.  *buffer = '\0';
  171.  *file_string = '\0';
  172.  
  173.  do
  174.  {
  175.  relocate();
  176.  HIGH_VIDEO;
  177.  _outtext("C Files:  ");
  178.  LOW_VIDEO;
  179.  
  180.  fgets (buffer, 80, stdin);
  181.  if (*buffer == '\n') exit(0);
  182.  strupr( buffer );
  183.  strL = strlen(buffer);
  184.  strncat (file_string, buffer, strL - (size_t) 1);
  185.  strL = strlen(file_string);
  186.  ampersand = reallocate(file_string, strL);
  187.  
  188.   } while (ampersand);
  189.  
  190.   return ( extract_file_names(file_string));
  191.  
  192.  
  193.  }
  194.  
  195. struct filespec  *extract_file_names(char *file_string)
  196.  {
  197.   char seps[] = " +";
  198.   struct filespec  *c_file_ptr, *previous, *c_file_start = NULL;
  199.  
  200.    if ( !(
  201.     c_file_ptr = (struct filespec *)
  202.        malloc ((size_t) sizeof (struct filespec) )
  203.        ) ) return (NULL);
  204.     if (!c_file_start) c_file_start = c_file_ptr;
  205.     c_file_ptr->next = NULL;
  206.  
  207.     c_file_ptr->path = strtok( file_string, seps );     /* Find first token        */
  208.     if (!c_file_ptr->path) return (NULL);
  209.     if (c_file_ptr->path)
  210.     if(*c_file_ptr->path == '&') return (NULL);
  211.  
  212.  
  213.     while( c_file_ptr->path != NULL )
  214.     {
  215.  
  216.    previous  = c_file_ptr;
  217.  
  218.    if ( !(
  219.     c_file_ptr = (struct filespec *)
  220.        malloc ((size_t) sizeof (struct filespec) )
  221.        ) ) return (NULL);
  222.  
  223.     c_file_ptr->next = NULL;
  224.     previous->next = c_file_ptr;
  225.     c_file_ptr->path = strtok( NULL, seps );   /* Find next token         */
  226.  
  227.   }
  228.  
  229.     if (c_file_start)  return c_file_start;
  230.     return (NULL);
  231.  }
  232.  
  233.  
  234. void instructions (void)
  235. {
  236.  _clearscreen(0);
  237.  HIGH_VIDEO;
  238.  _outtext("\nInstructions:  \n");
  239.  LOW_VIDEO;
  240.  printf(
  241. "Enter C files, separated by spaces or commas; if the files need more than\n"
  242. "one line, append an & to end of line and continue on to next line (do the\n"
  243. "same for each new line needed). The \'.C\' extension is assumed. [Note: it\n"
  244. "is also assumed that each new function begins on a new line and that\n"
  245. "function declarations conform to new ANSI style.]\n\n"
  246.   );
  247.  
  248.   relocate();
  249. }
  250.  
  251.  
  252. static int reallocate(char *file_string, size_t strL)
  253. {
  254.  int count;
  255.  static int line = 1;
  256.  char *p;
  257.  
  258.  
  259.  
  260.  for (p = file_string + (int) strL - 1, count = (int) strL;
  261.                           count;   count--, p++)
  262.     if (*p != ' ') break;
  263.  
  264.  strL = count;
  265.  count--;
  266.  if (file_string[count] == '&')  {
  267.      if (file_string[count - 1] != ' ') return(0);
  268.                  }
  269.                 else return(0);
  270.  
  271.  file_string[count] = ' ';
  272.  line++;
  273.  file_string = realloc(file_string, (strL + 81) * sizeof(char));
  274.  file_string[strL] = '\0';
  275.  return (1);
  276. }
  277.  
  278. void loop_through_modules (struct filespec *top, struct func **func_start,
  279.                                 FILE *rptfp)
  280. {
  281.   char fname[_MAX_FNAME];
  282.   FILE *fp;
  283.   struct func *start = NULL, *current_func = NULL;
  284.  
  285.    if (!top) return;
  286.    if (!declare_file) print_headings(0, rptfp );
  287.  
  288.   while (top->path)
  289.   {
  290.  
  291.   do
  292.   {
  293.   strcpy(fname, top->path);
  294.   fp = open_c_file(fname, rptfp);
  295.   if (!fp)  get_new_path(top);
  296.   }
  297.   while (!fp);
  298.  
  299.   user_hfile_only =  user_hf_FUNC;
  300.   start = main_loop(fp, rptfp, fname);
  301.   CurrentMod = fname;
  302.   user_hfile_only =  user_hf_VAR;
  303.   if (!declare_file)
  304.        current_func = record_variables(fp, rptfp, current_func, &start);
  305.   fclose(fp);
  306.   top = top->next;
  307.   }
  308.  
  309.   *func_start = start;   /* func_start = start of alphabetical linked list */
  310. }
  311.  
  312.  
  313. int paginate(FILE *rptfp)
  314. {
  315.  static int line_count = 0;
  316.  static int page = 2;
  317.  char dash = '-';
  318.  
  319.  if(declare_file) return (0);
  320.  
  321.  line_count++;
  322.  if (line_count > 59)
  323.     {
  324.       fprintf(rptfp, "\f\n%38c%d-\n\n",dash, page);
  325.       line_count = 4;
  326.       heading(rptfp, rpt_fname);
  327.       page++;
  328.       return(0);
  329.     }
  330.  
  331.   return(line_count);
  332. }
  333.  
  334. void formfeed(int line_count, FILE *rptfp)
  335. {
  336.   while(line_count )
  337.      line_count = paginate(rptfp);
  338. }
  339.  
  340.  
  341. static char *argv_cat(int argc, char **argv)
  342. {
  343.   int makefile = 0;
  344.   char *buffer;
  345.   buffer = (char *)malloc((size_t)argc * (size_t) (FILENAME_MAX + 1));
  346.   memset(buffer, 0, 14);
  347.  
  348.   *(argv++);
  349.    argc--;
  350.    if (!argc) exit_ca (BAD_ARGV, "");
  351.  
  352.     while (argc)
  353.      {
  354.       if(**argv == '@') {
  355.      strcpy(buffer, *(argv++));
  356.      makefile = 1;
  357.      argc--;
  358.      }
  359.       else if(!makefile) {
  360.        if(**argv != '/' && **argv != '-') {
  361.      strncat( buffer, *(argv++), (size_t)FILENAME_MAX );
  362.      argc--;
  363.      if (argc) strcat(buffer, "+");
  364.      }  else {
  365.          handle_switches(&argv, &argc);
  366.          argv++;
  367.          argc--;
  368.         }
  369.      }
  370.      else {
  371.      handle_switches(&argv, &argc);
  372.      argv++;
  373.      argc--;
  374.     }
  375.      }
  376.  
  377.  
  378.   strupr(buffer);
  379.   _outtext(buffer);
  380.   return(buffer);
  381.  
  382. }
  383.  
  384. #define RET_PATHVAR_ONLY  0x20
  385. char Rptfpath[_MAX_PATH];
  386. FILE *make_rptfile(char *path)
  387. {
  388.   char inpath[_MAX_PATH] ;
  389.   char drive[_MAX_DRIVE], dir[_MAX_DIR];
  390.   char fname[_MAX_FNAME], ext[_MAX_EXT] = "EXE";
  391.   char newpath[_MAX_PATH];
  392.   char *pathvar;
  393.   char rpt_ext[] = "rpt";
  394.   char cdecl_ext[] = "h$$";
  395.   char *ext_ptr;
  396.   size_t strL;
  397.   int result;
  398.  
  399.     if (declare_file)
  400.     ext_ptr = cdecl_ext;
  401.     else
  402.     ext_ptr = rpt_ext;
  403.  
  404.     _clearscreen(0);
  405.     HIGH_VIDEO;
  406.  
  407.     relocate();
  408.     pathvar = get_envpath(RET_PATHVAR_ONLY, "INCLUDE", inpath);
  409.     if (!pathvar) {
  410.        _outtext("INLUDE variable not found\n");
  411.        _outtext("\nPress TAB to use Current Directory, ");
  412.        }
  413.       else {
  414.      _outtext("INCLUDE = ");
  415.      _outtext(pathvar);
  416.      _outtext("\nPress ENTER to Accept, ");
  417.      }
  418.    _outtext("'Q' to Abort, ESC to Revise.\n");
  419.     do
  420.     {
  421.       result = getch();
  422.       if (result == 0 || result == 0xE0) getch();
  423.  
  424.       if (result == (int)'q' || result == (int)'Q') exit (0);
  425.     } while (result != 27 && result != 13  && result != 9);
  426.     if (result == 9 && !pathvar) {
  427.      if (getcwd(inpath, 127)) pathvar = makepathvar(inpath,pathvar);
  428.     }
  429.     else if(result == 27) {
  430.        _outtext("\nNew Include variable: ");
  431.        gets(inpath);
  432.        if (*inpath) {
  433.       pathvar = makepathvar(inpath,pathvar);}
  434.        }
  435.     strncpy (inpath, path, _MAX_PATH);
  436.     strL = strlen(inpath);
  437.     inpath[strL] = '\0';
  438.    _splitpath( inpath, drive, dir, fname, ext );
  439.    _makepath( Rptfpath, drive, dir, fname, ext_ptr );
  440.  
  441.    _makepath( rpt_fname, "", "", fname, ext_ptr );
  442.  
  443.     relocate();
  444.     if (declare_file)
  445.      _outtext("\nHeader File [");
  446.      else _outtext("\nReport File [");
  447.     _outtext(Rptfpath);
  448.     _outtext("]: ");
  449.     LOW_VIDEO;
  450.  
  451.     fgets (newpath, _MAX_PATH - 1, stdin);
  452.     if (*newpath != '\n') {
  453.     strL = strlen(newpath);
  454.     newpath[(int) --strL] = '\0';
  455.        _splitpath( newpath, drive, dir, rpt_fname, ext );
  456.        _makepath( Rptfpath, drive, dir, rpt_fname, rpt_ext );
  457.        strcat(rpt_fname, ext);
  458.           }
  459.      relocate();
  460.      return(open_reportfile(START_RPT));
  461. }
  462.  
  463.  
  464. FILE *open_c_file(char *filepath, FILE *rptfp)
  465. {
  466.   char drive[_MAX_DRIVE], dir[_MAX_DIR];
  467.   char fname[_MAX_FNAME], ext[_MAX_EXT] ;
  468.   char c_ext[] = ".C";
  469.   char newpath[_MAX_PATH];
  470.   FILE *fp;
  471.  
  472.  _splitpath(filepath, drive, dir, fname, ext );
  473.  if (!*ext) strcpy (ext, c_ext);
  474.  _makepath(newpath, drive, dir, fname, ext);
  475.  
  476.   if (declare_file)
  477.      fprintf (rptfp,"\n/*   %s%s   */\n",fname, ext );
  478.    else
  479.     fprintf (rptfp,"\n%s%s\n",fname, ext );
  480.  
  481.   paginate(rptfp);
  482.  
  483.   if (   (fp = fopen( newpath, "rt") ) == NULL )
  484.        {
  485.        relocate();
  486.        printf ("cannot open file: %s\n", filepath);
  487.        fprintf (rptfp, "cannot open file: %s\n", filepath);
  488.        return (NULL);
  489.        }
  490.    strcpy(filepath, fname);
  491.    return(fp);
  492.   }
  493.  
  494.  
  495.  
  496. void get_new_path(struct filespec *top)
  497. {
  498.  char *new_file_buf, buffer[81];
  499.  size_t strL;
  500.  
  501.  _outtext("\nEnter revised filespec or type Enter to Exit\n");
  502.   HIGH_VIDEO;
  503.   relocate();
  504.  _outtext("\nC File: ");
  505.   LOW_VIDEO;
  506.  fgets (buffer, 80, stdin);
  507.  relocate();
  508.  
  509.  if (*buffer == '\n') exit (2);
  510.  
  511.  strL = strlen(buffer);
  512.  strL--;
  513.  *(buffer + strL) = '\0';
  514.  strupr(buffer);
  515.  
  516.  new_file_buf = (char *) calloc ((size_t) 81, sizeof(char));
  517.  if (!new_file_buf) exit_ca (BAD_FILE_BUF, "");
  518.  
  519.  strcpy (new_file_buf, buffer);
  520.  top->path = new_file_buf;
  521.  
  522. }
  523.  
  524. union REGS regs;
  525.  
  526. static void crt_grc(int *row, int *col)
  527. {
  528.    regs.h.ah = 3;
  529.    regs.h.bh = 0;         /* page=0 */
  530.    int86(0x10, ®s, ®s);   /* Use video int fctn = 6 */
  531.    *row = regs.h.dh; *col = regs.h.dl;
  532. }
  533.  
  534. void relocate(void)
  535. {
  536.   int row, col;
  537.  
  538.   crt_grc(&row, &col);
  539.   if(row <= 1) _clearscreen(0);
  540.   if (row < 24 ) row++;
  541.     else _outtext("                      ");
  542.   _settextposition((short)row, (short) 1);
  543. }
  544.  
  545. void handle_switches(char ***cmdline_switch, int *argc)
  546. {
  547.    char *p, *__switch = NULL ;
  548.    char no_equal[] = "Missing Equal Sign: Recommend Abort.";
  549.    int c;
  550.  
  551.    switches_found = 1;   /* global for use in main */
  552.    (**cmdline_switch)++;
  553.    p = **cmdline_switch;
  554.    while ( iswhite(*p) ) p++;
  555.    strupr(p);
  556.  
  557.      switch (*p)
  558.      {
  559.       case 'C':
  560.      /*  CDECLARE: /CDE  */
  561.      /* Creates a 'C'  Declarations file from all modules */
  562.      if ( *(p + 1) == 'D' && *(p + 2) == 'E') {
  563.         declare_file = 1;
  564.         return;
  565.     }
  566.     break;
  567.  
  568.       case  'F':
  569.        /*  Set size of FUNCTION POINTER STACK  */
  570.        if ( *(p + 1) == 'P' && *(p + 2) == 'S') {
  571.          if( !(__switch =  parse_switch(cmdline_switch, argc, p) ) )
  572.                                   break;
  573.          GLfpSsize = atoi(__switch);
  574.          return;
  575.          }
  576.       break;
  577.  
  578.  
  579.       case  'I':
  580.       /*INCLUDE: /INC */
  581.       /* Sets New INCLUDE directory */
  582.       if ( *(p + 1) == 'N' && *(p + 2) == 'C') {
  583.           if( !(__switch =  parse_switch(cmdline_switch, argc, p)))
  584.                                 break;
  585.           strncat(NewInclude, __switch, 127);
  586.           if( putenv (NewInclude) == -1 ) break;
  587.           return;
  588.          }
  589.        if ( *(p + 1) == 'F' && *(p + 2) == 'D') {
  590.          IfDefOFF = 1;
  591.          return;
  592.          }
  593.          break;
  594.       case 'N':
  595.       /*NOINCLUDE   /NOI */
  596.       if ( *(p + 1) == 'O' && *(p + 2) == 'I') {
  597.       __Inclf_Limit = 0;
  598.       return;
  599.       }
  600.       /* NO COMPLEX DECLARATORS:  /NCX */
  601.       if ( *(p + 1) == 'C' && *(p + 2) == 'X') {
  602.       __Complex_Declarators = 0;
  603.       return;
  604.       }
  605.  
  606.       break;
  607.       case 'L':
  608.       /* LEVEL  /LEV */
  609.       /* Sets number of include file levels which will be opened */
  610.       /* Default is 5 */
  611.        if ( *(p + 1) == 'E' && *(p + 2) == 'V') {
  612.          if( !(__switch =  parse_switch(cmdline_switch, argc, p) ) )
  613.                                   break;
  614.          __Inclf_Limit = atoi(__switch);
  615.          if  (__Inclf_Limit > 8) __Inclf_Limit = 8;
  616.          return;
  617.          }
  618.       break;
  619.  
  620.       case 'R':
  621.      /* REDIRECT SCREEN OUTPUT TO FILE:  /RED */
  622.      if ( *(p + 1) == 'E' && *(p + 2) == 'D') {
  623.      if (!(scrn_out = get_redfp()) ) scrn_out = stdout;
  624.     return;
  625.     }
  626.     break;
  627.  
  628.       case  'S':
  629.       /* SPLIT REPORT FILE INTO TWO OR THREE FILES: /SPF=n */
  630.        if ( *(p + 1) == 'R' && *(p + 2) == 'F') {
  631.          if( !(__switch =  parse_switch(cmdline_switch, argc, p) ) )
  632.                                   break;
  633.          SplitNumber_rpf = atoi(__switch);
  634.          if(SplitNumber_rpf > 3) SplitNumber_rpf = 3;
  635.          return;
  636.          }
  637.       break;
  638.  
  639.       case 'U':
  640.       /* USER HEADER FILES ONLY:  /UHF */
  641.      if ( *(p + 1) == 'H' && *(p + 2) == 'F') {
  642.  
  643.         if(*(p + 3) == ':')  {
  644.           if(*(p + 4) == 'V')
  645.          user_hf_VAR = 1;
  646.           else if(*(p + 4) == 'F')
  647.          user_hf_FUNC = 1;
  648.           return;
  649.           }
  650.  
  651.         user_hf_VAR = 1;
  652.         user_hf_FUNC = 1;
  653.         return;
  654.     }
  655.     break;
  656.  
  657.       case 'V':
  658.      /* VERBOSE=1 SWITCHES ON REPORTING OF WHETHER OR NOT DEFINES */
  659.      /* HAVE BEEN FOUND */
  660.     if ( *(p + 1) == 'E' && *(p + 2) == 'R') {
  661.        verbose = 1;
  662.     }
  663.     break;
  664.      }
  665.  
  666.  
  667.  if (!__switch) p = no_equal;
  668.  printf
  669.  ("Unrecognized switch: %s\nESC to exit, Any other Key to Continue\n", p);
  670.  c = getch();
  671.  if (c == 27) exit(0);
  672.  
  673. }
  674.  
  675.  
  676. char *parse_switch(char ***cmdline_switch, int *argc, char *p)
  677. {
  678.  char *equal_to = NULL;
  679.  
  680.     if ( !(equal_to = strchr(p, '=') )) {
  681.         equal_to = *((*cmdline_switch + 1));
  682.         if (equal_to) {
  683.           if ( !(equal_to = strchr(p, '=') )) return (equal_to);
  684.           *argc-=2;
  685.           return (*(*cmdline_switch += 2));
  686.           }
  687.           }
  688.           else {
  689.           *(++equal_to);
  690.           if (!*equal_to) {
  691.             equal_to = *((*cmdline_switch + 1));
  692.             if (equal_to) {
  693.               *argc-=1;
  694.               return (*(*cmdline_switch += 1));
  695.               }
  696.               }
  697.           }
  698.  
  699.       return(equal_to);
  700. }
  701.  
  702. char *readmakefile(char *file_string)
  703. {
  704.  char makefile[FILENAME_MAX + 1];
  705.  FILE *fp;
  706.  char buffer[160], *ptr, *newline;
  707.  size_t strL = 0;
  708.  
  709.  strncpy (makefile, (file_string + 1), FILENAME_MAX);
  710.  makefile[FILENAME_MAX] = '\0';
  711.  if( (fp = fopen( makefile, "rt" )) == NULL ) return(NULL);
  712.  
  713.  while (  fgets (buffer, 160, fp) ) strL += (strlen(buffer) + 1);
  714.  
  715.  file_string = realloc(file_string, strL);
  716.  memset(file_string, 0, strL);
  717.  
  718.  
  719.  rewind(fp);
  720.  while (  fgets (buffer, 160, fp) ) {
  721.    ptr = buffer;
  722.    while (*ptr && is_in(*ptr, " \n")) ptr++;
  723.    if (*ptr) {
  724.     newline = strchr(ptr, '\n');
  725.     if (newline) *newline = '\0';
  726.     newline = strchr(ptr, '&');
  727.     if (newline) *newline = '\0';
  728.     strupr(ptr);
  729.     strcat(file_string, ptr);
  730.     strcat(file_string, " ");
  731.     }
  732.    }
  733.  
  734.  
  735.  fclose(fp);
  736.  return(file_string);
  737. }
  738.  
  739.  
  740. char *makepathvar(char *inpath, char *pathvar)
  741. {
  742.   size_t strL;
  743.  
  744.        pathvar =  strchr(NewInclude, '=');
  745.        strL = strlen(inpath);
  746.        if(strL > 137) strL = 137;
  747.        strncat(++pathvar, inpath, strL);
  748.       *(pathvar + strL) = '\0';
  749.       if( (putenv(NewInclude)) == -1) {
  750.     _outtext("\nError in setting Include variable\n");
  751.     return (NULL);
  752.     }
  753.       return(pathvar);
  754. }
  755.  
  756.  
  757. static FILE * open_reportfile(int rpt_number)
  758. {
  759.     static FILE *rptfp;
  760.     static char *revrpt[] =  { "PT2.RPT", "PT3.RPT" };
  761.  
  762.  
  763.     if (rpt_number != START_RPT) {
  764.       size_t ext;
  765.       char *p = Rptfpath;
  766.       fclose(rptfp);
  767.       ext = strcspn(Rptfpath, ".");
  768.       ext = (ext > 3) ? (ext - 3) : 1;
  769.       *(p + ext) = '\0';
  770.       strcat(Rptfpath, revrpt[rpt_number]);
  771.     }
  772.  
  773.     if (   (rptfp = fopen( Rptfpath, "wt") ) == NULL )
  774.       {
  775.        exit_ca (BAD_FILE, Rptfpath);
  776.      }
  777.  
  778.    if (rpt_number == START_RPT) {
  779.        date_time(rptfp);
  780.        heading(rptfp, rpt_fname);
  781.     }
  782.  
  783.     return(rptfp);
  784. }
  785.  
  786. /*lint +epu */
  787.