home *** CD-ROM | disk | FTP | other *** search
/ Dream 57 / Amiga_Dream_57.iso / Amiga / Programmation / c / Docs / cxref-1.4a.lha / cxref.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-12-16  |  22.9 KB  |  815 lines

  1. /***************************************
  2.   $Header: /home/amb/cxref/RCS/cxref.c 1.35 1997/11/20 19:57:39 amb Exp $
  3.  
  4.   C Cross Referencing & Documentation tool. Version 1.4a.
  5.   ******************/ /******************
  6.   Written by Andrew M. Bishop
  7.  
  8.   This file Copyright 1995,96,97 Andrew M. Bishop
  9.   It may be distributed under the GNU Public License, version 2, or
  10.   any higher version.  See section COPYING of the GNU Public license
  11.   for conditions under which this file may be redistributed.
  12.   ***************************************/
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/types.h>
  18. #ifndef __SASC    /* olsen: does not exist with SAS/C */
  19. #include <sys/wait.h>
  20. #endif /* __SASC */
  21. #include <sys/stat.h>
  22. #include <unistd.h>
  23.  
  24. #ifdef AMIGA    /* olsen */
  25. #include "amiga.h"
  26. #endif /* AMIGA */
  27.  
  28. #include "parse-yy.h"
  29. #include "memory.h"
  30. #include "datatype.h"
  31. #include "cxref.h"
  32.  
  33. /*+ The default value of the CPP command. +*/
  34. #ifdef CXREF_CPP
  35. #define CPP_COMMAND CXREF_CPP
  36. #else
  37. #define CPP_COMMAND "gcc -E -C -dD -dI"
  38. #endif
  39.  
  40. /*+ The name of the file to read the configuration from. +*/
  41. #define CXREF_CONFIG_FILE ".cxref"
  42.  
  43.  
  44. static void Usage(int verbose);
  45. static int ParseConfigFile(void);
  46. static int ParseOptions(int nargs,char **args,int is_argv);
  47.  
  48. static int DocumentTheFile(char* name);
  49. static FILE* popen_execvp(char** command);
  50. static int pclose_execvp(FILE* f);
  51.  
  52. static char** cpp_command;              /*+ The actual cpp command that is built up, adding -D, -U and -I options. +*/
  53. static int cpp_command_num=0;           /*+ The number of arguments to the cpp command. +*/
  54.  
  55. /*+ The command line switch that sets the format of the output, +*/
  56. int option_all_comments=0,              /*+ use all comments. +*/
  57.     option_verbatim_comments=0,         /*+ insert the comments verbatim into the output. +*/
  58.     option_block_comments=0,            /*+ remove the leading block comment marker. +*/
  59.     option_no_comments=0,               /*+ ignore all comments. +*/
  60.     option_xref=0,                      /*+ do cross referencing. +*/
  61.     option_warn=0,                      /*+ produce warnings. +*/
  62.     option_index=0,                     /*+ produce an index. +*/
  63.     option_raw=0,                       /*+ produce raw output. +*/
  64.     option_latex=0,                     /*+ produce latex output. +*/
  65.     option_html=0;                      /*+ produce html output. +*/
  66.  
  67. /*+ The option to control the mode of operation. +*/
  68. int option_delete=0;
  69.  
  70. /*+ The command line switch for the output name, +*/
  71. char *option_odir=".",                  /*+ the directory to use. +*/
  72.      *option_name="cxref",              /*+ the base part of the name. +*/
  73.      *option_root=NULL;                 /*+ the source tree root directory. +*/
  74.  
  75. /*+ The name of the include directories specified on the command line. +*/
  76. char **option_incdirs=NULL;
  77.  
  78. /*+ The number of include directories on the command line. +*/
  79. int option_nincdirs=0;
  80.  
  81. /*+ The current file that is being processed. +*/
  82. File CurFile=NULL;
  83.  
  84.  
  85. /*++++++++++++++++++++++++++++++++++++++
  86.   The main function that calls the parser.
  87.  
  88.   int main Returns the status, zero for normal termination, else an error.
  89.  
  90.   int argc The command line number of arguments.
  91.  
  92.   char** argv The actual command line arguments
  93.   ++++++++++++++++++++++++++++++++++++++*/
  94.  
  95. int main(int argc,char** argv)
  96. {
  97.  int i;
  98.  char *root_prefix=NULL;
  99.  
  100.  #ifdef AMIGA /* olsen */
  101.  {
  102.    expand_args(argc,argv,&argc,&argv,0,1);
  103.  }
  104.  #endif /* AMIGA */
  105.  
  106.  if(argc==1)
  107.     Usage(1);
  108.  
  109.  cpp_command=(char**)Malloc(8*sizeof(char*));
  110.  cpp_command[cpp_command_num++]=MallocString(CPP_COMMAND);
  111.  
  112.  for(i=1;i<strlen(CPP_COMMAND);i++)
  113.     if(cpp_command[0][i]==' ')
  114.        cpp_command[0][i]=0;
  115.     else
  116.        if(cpp_command[0][i-1]==0)
  117.          {
  118.           if((cpp_command_num%8)==6)
  119.              cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
  120.           cpp_command[cpp_command_num++]=&cpp_command[0][i];
  121.          }
  122.  
  123.  option_incdirs=(char**)Malloc(8*sizeof(char*));
  124.  option_incdirs[0]=".";
  125.  option_nincdirs=1;
  126.  
  127.  /* Parse the command line options. */
  128.  
  129.  if(ParseOptions(argc-1,&argv[1],1))
  130.     Usage(0);
  131.  
  132.  /* Parse the options in .cxref in this directory. */
  133.  
  134.  if(ParseConfigFile())
  135.     Usage(0);
  136.  
  137.  /* Change directory. */
  138.  
  139.  if(option_root)
  140.    {
  141.     char *here=(char*)Malloc(512),*there=(char*)Malloc(512);
  142.  
  143.     if(!getcwd(there,255))
  144.       {fprintf(stderr,"cxref: Error cannot get current working directory (1).\n");exit(1);}
  145.     if(chdir(option_root))
  146.       {fprintf(stderr,"cxref: Error cannot change directory to '%s'.\n",option_root);exit(1);}
  147.     if(!getcwd(here,255))
  148.       {fprintf(stderr,"cxref: Error cannot get current working directory (2).\n");exit(1);}
  149.  
  150.     if(!strncmp(here,there,strlen(here)))
  151.        root_prefix=there+strlen(here)+1;
  152.     else
  153.       {fprintf(stderr,"cxref: Error the -R option has not specified a parent directory of the current one.\n");exit(1);}
  154.  
  155.     for(i=1;i<cpp_command_num;i++)
  156.        if(cpp_command[i][0]=='-' && cpp_command[i][1]=='I')
  157.          {
  158.           if(cpp_command[i][2]==0)
  159.             {
  160.              if(cpp_command[++i][0]!='/')
  161.                 cpp_command[i]=MallocString(CanonicaliseName(ConcatStrings(3,root_prefix,"/",cpp_command[i])));
  162.             }
  163.           else if(cpp_command[i][2]!='/')
  164.              cpp_command[i]=MallocString(ConcatStrings(2,"-I",CanonicaliseName(ConcatStrings(3,root_prefix,"/",cpp_command[i]+2))));
  165.          }
  166.  
  167.     for(i=0;i<option_nincdirs;i++)
  168.        if(*option_incdirs[i]!='/')
  169.           option_incdirs[i]=MallocString(CanonicaliseName(ConcatStrings(3,root_prefix,"/",option_incdirs[i])));
  170.  
  171.     if(ParseConfigFile())
  172.        Usage(0);
  173.    }
  174.  
  175.  /* Process each file. */
  176.  
  177.  for(i=1;i<argc;i++)
  178.     if(argv[i])
  179.       {
  180.        char *filename=CanonicaliseName(root_prefix?ConcatStrings(3,root_prefix,"/",argv[i]):argv[i]);
  181.  
  182.        if(!option_delete)
  183.          {
  184.           CurFile=NewFile(filename);
  185.  
  186.           if(!DocumentTheFile(filename))
  187.             {
  188.              if(option_xref)
  189.                 CrossReference(CurFile);
  190.  
  191.              if(option_raw || option_warn)
  192.                 WriteWarnRawFile(CurFile);
  193.              if(option_latex)
  194.                 WriteLatexFile(CurFile);
  195.              if(option_html)
  196.                 WriteHTMLFile(CurFile);
  197.             }
  198.  
  199.           ResetLexer();
  200.           ResetParser();
  201.           ResetPreProcAnalyser();
  202.           ResetTypeAnalyser();
  203.           ResetVariableAnalyser();
  204.           ResetFunctionAnalyser();
  205.  
  206.           DeleteFile(CurFile);
  207.           CurFile=NULL;
  208.          }
  209.        else
  210.          {
  211.           CrossReferenceDelete(filename);
  212.  
  213.           WriteLatexFileDelete(filename);
  214.           WriteHTMLFileDelete(filename);
  215.          }
  216.  
  217.        TidyMemory();
  218.       }
  219.  
  220.  /* Create the index */
  221.  
  222.  if(option_index)
  223.    {
  224.     StringList files;
  225.     StringList2 funcs,vars,types;
  226.  
  227.     files=NewStringList();
  228.     funcs=NewStringList2();
  229.     vars=NewStringList2();
  230.     types=NewStringList2();
  231.  
  232.     CreateAppendix(files,funcs,vars,types);
  233.  
  234.     if(option_raw||option_warn)
  235.        WriteWarnRawAppendix(files,funcs,vars,types);
  236.     if(option_latex)
  237.        WriteLatexAppendix(files,funcs,vars,types);
  238.     if(option_html)
  239.        WriteHTMLAppendix(files,funcs,vars,types);
  240.  
  241.     DeleteStringList(files);
  242.     DeleteStringList2(funcs);
  243.     DeleteStringList2(vars);
  244.     DeleteStringList2(types);
  245.  
  246.     TidyMemory();
  247.    }
  248.  
  249.  /* Tidy up */
  250.  
  251.  Free(cpp_command[0]);
  252.  Free(cpp_command);
  253.  
  254.  Free(option_incdirs);
  255.  
  256.  PrintMemoryStatistics();
  257.  
  258.  return(0);
  259. }
  260.  
  261.  
  262. /*++++++++++++++++++++++++++++++++++++++
  263.   Print out the usage instructions.
  264.  
  265.   int verbose If true then output a long version of the information.
  266.   ++++++++++++++++++++++++++++++++++++++*/
  267.  
  268. static void Usage(int verbose)
  269. {
  270.  fputs("\n"
  271.        "              C Cross Referencing & Documenting tool - Version 1.4a\n"
  272.        "              -----------------------------------------------------\n"
  273.        "\n"
  274.        "(c) Andrew M. Bishop 1995,96,97  [       amb@gedanken.demon.co.uk ]\n"
  275.        "                                 [http://www.gedanken.demon.co.uk/]\n"
  276.        "\n"
  277.        "Usage: cxref filename [ ... filename]\n"
  278.        "             [-Odirname] [-Nbasename] [-Rdirname]\n"
  279.        "             [-all-comments] [-no-comments]\n"
  280.        "             [-verbatim-comments] [-block-comments]\n"
  281.        "             [-xref[-all][-file][-func][-var][-type]]\n"
  282.        "             [-warn[-all][-comment][-xref]]\n"
  283.        "             [-index[-all][-file][-func][-var][-type]]\n"
  284.        "             [-raw] [-latex|-latex2e] [-html]\n"
  285.        "             [-Idirname] [-Ddefine] [-Udefine]\n"
  286.        "             [-CPP cpp_program] [-- cpp_arg [ ... cpp_arg]]\n"
  287.        "\n"
  288.        "Usage: cxref filename [ ... filename] -delete\n"
  289.        "             [-Odirname] [-Nbasename] [-Rdirname]\n"
  290.        "\n",
  291.        stderr);
  292.  
  293.  if(verbose)
  294.     fputs("filename ...           : Files to document.\n"
  295.           "-delete                : Delete all references to the named files.\n"
  296.           "\n"
  297.           "-Odirname              : The output directory for the documentation.\n"
  298.           "-Nbasename             : The base filename for the output documentation.\n"
  299.           "-Rdirname              : The root directory of the source tree.\n"
  300.           "\n"
  301.           "-all-comments          : Use all comments.\n"
  302.           "-verbatim-comments     : Insert the comments verbatim in the output.\n"
  303.           "-block-comments        : The comments are in block style.\n"
  304.           "-no-comments           : Ignore all of the comments.\n"
  305.           "\n"
  306.           "-xref[-*]              : Do cross referencing (of specified types).\n"
  307.           "-warn[-*]              : Produce warnings (of comments or cross references).\n"
  308.           "\n"
  309.           "-index[-*]             : Produce a cross reference index (of specified types).\n"
  310.           "\n"
  311.           "-raw                   : Produce raw output.\n"
  312.           "-latex | -latex2e      : Produce LaTeX output (version 2.09 or 2e).\n"
  313.           "-html                  : Produce HTML output (version 2.0).\n"
  314.           "\n"
  315.           "-I*, -D*, -U*          : The usual compiler switches.\n"
  316.           "-CPP cpp_program       : The cpp program to use.\n"
  317.           "                       : (default '" CPP_COMMAND "')\n"
  318.           "-- cpp_arg ...         : All arguments after the '--' are passed to cpp.\n"
  319.           "\n"
  320.           "The file .cxref in the current directory can also contain any of these arguments\n"
  321.           "one per line, (except for filename and -delete).\n",
  322.           stderr);
  323.  else
  324.     fputs("Run cxref with no arguments to get more verbose help\n",
  325.           stderr);
  326.  
  327.  exit(1);
  328. }
  329.  
  330.  
  331. /*++++++++++++++++++++++++++++++++++++++
  332.   Read in the options from the configuration file.
  333.  
  334.   int ParseConfigFile Returns the values returned by ParseOptions().
  335.   ++++++++++++++++++++++++++++++++++++++*/
  336.  
  337. static int ParseConfigFile(void)
  338. {
  339.  FILE *file=fopen(CXREF_CONFIG_FILE,"r");
  340.  char **lines=NULL;
  341.  int nlines=0;
  342.  char data[129];
  343.  
  344.  if(file)
  345.    {
  346.     while(fgets(data,80,file))
  347.       {
  348.        char *d=data+strlen(data)-1;
  349.  
  350.        if(*data=='#')
  351.           continue;
  352.  
  353.        while(d>=data && (*d=='\r' || *d=='\n' || *d==' '))
  354.           *d--=0;
  355.  
  356.        if(d<data)
  357.           continue;
  358.  
  359.        if(!lines)
  360.           lines=(char**)Malloc(8*sizeof(char*));
  361.        else if((nlines%8)==7)
  362.           lines=(char**)Realloc(lines,(nlines+9)*sizeof(char*));
  363.  
  364.        if((!strncmp(data,"-I",2) || !strncmp(data,"-D",2) || !strncmp(data,"-U",2) ||
  365.            !strncmp(data,"-O",2) || !strncmp(data,"-N",2) || !strncmp(data,"-R",2)) &&
  366.           (data[2]==' ' || data[2]=='\t'))
  367.          {
  368.           int i=2;
  369.           while(data[i]==' ' || data[i]=='\t')
  370.              data[i++]=0;
  371.           lines[nlines++]=MallocString(data);
  372.           lines[nlines++]=MallocString(data+i);
  373.          }
  374.        else if(!strncmp(data,"-CPP",4) &&
  375.                (data[4]==' ' || data[4]=='\t'))
  376.          {
  377.           int i=4;
  378.           while(data[i]==' ' || data[i]=='\t')
  379.              data[i++]=0;
  380.           lines[nlines++]=MallocString(data);
  381.           lines[nlines++]=MallocString(data+i);
  382.          }
  383.        else
  384.           if(*data)
  385.              lines[nlines++]=MallocString(data);
  386.       }
  387.  
  388.     if(nlines)
  389.       {
  390.        if(ParseOptions(nlines,lines,0))
  391.           return(1);
  392.  
  393.        Free(lines);
  394.       }
  395.  
  396.     fclose(file);
  397.    }
  398.  
  399.  return(0);
  400. }
  401.  
  402. /*++++++++++++++++++++++++++++++++++++++
  403.   Parse the options from the command line or from the .cxref file.
  404.  
  405.   int ParseOptions Return 1 if there is an error.
  406.  
  407.   int nargs The number of arguments.
  408.  
  409.   char **args The actual arguments
  410.  
  411.   int is_argv Set to true if these are the argc,argv values.
  412.   ++++++++++++++++++++++++++++++++++++++*/
  413.  
  414. static int ParseOptions(int nargs,char **args,int is_argv)
  415. {
  416.  int i,end_of_args=0;
  417.  int cpp_original_num=cpp_command_num;
  418.  
  419.  for(i=0;i<nargs;i++)
  420.    {
  421.     if(end_of_args)
  422.       {
  423.        if((cpp_command_num%8)==6)
  424.           cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
  425.        cpp_command[cpp_command_num++]=args[i];
  426.        if(is_argv) args[i]=NULL;
  427.        continue;
  428.       }
  429.  
  430.     if(!strncmp(args[i],"-I",2) || !strncmp(args[i],"-D",2) || !strncmp(args[i],"-U",2))
  431.       {
  432.        char *incdir=NULL;
  433.        if((cpp_command_num%8)==6)
  434.           cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
  435.        cpp_command[cpp_command_num++]=args[i];
  436.        if(args[i][2]==0)
  437.          {
  438.           if(args[i][1]=='I')
  439.              incdir=args[i+1];
  440.           if(i==nargs-1)
  441.             {fprintf(stderr,"cxref: The -%c option requires a following argument.\n",args[i][1]);return(1);}
  442.           if(is_argv) args[i]=NULL;
  443.           if((cpp_command_num%8)==6)
  444.              cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
  445.           cpp_command[cpp_command_num++]=args[++i];
  446.          }
  447.        else
  448.           if(args[i][1]=='I')
  449.              incdir=&args[i][2];
  450.        if(is_argv) args[i]=NULL;
  451.  
  452.        if(incdir)
  453.          {
  454.           if((option_nincdirs%8)==0)
  455.              option_incdirs=(char**)Realloc(option_incdirs,(option_nincdirs+8)*sizeof(char*));
  456.           option_incdirs[option_nincdirs++]=incdir;
  457.          }
  458.        continue;
  459.       }
  460.  
  461.     if(!strcmp(args[i],"-CPP"))
  462.       {
  463.        char **old=cpp_command,*command;
  464.        int j,old_num=cpp_command_num;
  465.  
  466.        if(args[i][4]==0)
  467.          {
  468.           if(i==nargs-1)
  469.             {fprintf(stderr,"cxref: The -CPP option requires a following argument.\n");return(1);}
  470.           if(is_argv) args[i]=NULL;
  471.           command=args[++i];
  472.          }
  473.        else
  474.           command=&args[i][4];
  475.  
  476.        cpp_command_num=0;
  477.        cpp_command=(char**)Malloc(8*sizeof(char*));
  478.        cpp_command[cpp_command_num++]=MallocString(command);
  479.  
  480.        for(j=1;j<strlen(command);j++)
  481.           if(cpp_command[0][j]==' ')
  482.              cpp_command[0][j]=0;
  483.           else
  484.              if(cpp_command[0][j-1]==0)
  485.                {
  486.                 if((cpp_command_num%8)==6)
  487.                    cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
  488.                 cpp_command[cpp_command_num++]=&cpp_command[0][j];
  489.                }
  490.  
  491.        for(j=cpp_original_num;j<old_num;j++)
  492.          {
  493.           if((cpp_command_num%8)==6)
  494.              cpp_command=(char**)Realloc(cpp_command,(cpp_command_num+10)*sizeof(char*));
  495.           cpp_command[cpp_command_num++]=old[j];
  496.          }
  497.  
  498.        cpp_original_num=cpp_command_num;
  499.        Free(old[0]); Free(old);
  500.  
  501.        if(is_argv) args[i]=NULL;
  502.        continue;
  503.       }
  504.  
  505.     if(!strncmp(args[i],"-O",2))
  506.       {
  507.        if(args[i][2]==0)
  508.          {
  509.           if(i==nargs-1)
  510.             {fprintf(stderr,"cxref: The -O option requires a following argument.\n");return(1);}
  511.           if(is_argv) args[i]=NULL;
  512.           option_odir=args[++i];
  513.          }
  514.        else
  515.           option_odir=&args[i][2];
  516.        if(is_argv) args[i]=NULL;
  517.        continue;
  518.       }
  519.  
  520.     if(!strncmp(args[i],"-N",2))
  521.       {
  522.        if(args[i][2]==0)
  523.          {
  524.           if(i==nargs-1)
  525.             {fprintf(stderr,"cxref: The -N option requires a following argument.\n");return(1);}
  526.           if(is_argv) args[i]=NULL;
  527.           option_name=args[++i];
  528.          }
  529.        else
  530.           option_name=&args[i][2];
  531.        if(is_argv) args[i]=NULL;
  532.        continue;
  533.       }
  534.  
  535.     if(!strncmp(args[i],"-R",2))
  536.       {
  537.        if(args[i][2]==0)
  538.          {
  539.           if(i==nargs-1)
  540.             {fprintf(stderr,"cxref: The -R option requires a following argument.\n");return(1);}
  541.           if(is_argv) args[i]=NULL;
  542.           option_root=args[++i];
  543.          }
  544.        else
  545.           option_root=&args[i][2];
  546.        if(is_argv) args[i]=NULL;
  547.        continue;
  548.       }
  549.  
  550.     if(!strcmp(args[i],"-delete"))
  551.       {option_delete=1; if(is_argv)args[i]=NULL; continue;}
  552.  
  553.     if(!strcmp(args[i],"-all-comments"))
  554.       {option_all_comments=1; if(is_argv)args[i]=NULL; continue;}
  555.  
  556.     if(!strcmp(args[i],"-verbatim-comments"))
  557.       {option_verbatim_comments=1; if(is_argv)args[i]=NULL; continue;}
  558.  
  559.     if(!strcmp(args[i],"-block-comments"))
  560.       {option_block_comments=1; if(is_argv)args[i]=NULL; continue;}
  561.  
  562.     if(!strcmp(args[i],"-no-comments"))
  563.       {option_no_comments=1; if(is_argv)args[i]=NULL; continue;}
  564.  
  565.     if(!strncmp(args[i],"-xref",5))
  566.       {
  567.        char* p=&args[i][5];
  568.  
  569.        if(!*p)
  570.           option_xref=XREF_ALL;
  571.        else
  572.           while(*p)
  573.             {
  574.              if(!strncmp(p,"-all" ,4)) {option_xref|=XREF_ALL ; p=&p[4]; continue;}
  575.              if(!strncmp(p,"-file",5)) {option_xref|=XREF_FILE; p=&p[5]; continue;}
  576.              if(!strncmp(p,"-func",5)) {option_xref|=XREF_FUNC; p=&p[5]; continue;}
  577.              if(!strncmp(p,"-var" ,4)) {option_xref|=XREF_VAR ; p=&p[4]; continue;}
  578.              if(!strncmp(p,"-type",5)) {option_xref|=XREF_TYPE; p=&p[5]; continue;}
  579.              break;
  580.             }
  581.        if(is_argv) args[i]=NULL;
  582.        continue;
  583.       }
  584.  
  585.     if(!strncmp(args[i],"-warn",5))
  586.       {
  587.        char* p=&args[i][5];
  588.  
  589.        if(!*p)
  590.           option_warn=WARN_ALL;
  591.        else
  592.           while(*p)
  593.             {
  594.              if(!strncmp(p,"-all"    ,4)) {option_warn|=WARN_ALL    ; p=&p[4]; continue;}
  595.              if(!strncmp(p,"-comment",8)) {option_warn|=WARN_COMMENT; p=&p[8]; continue;}
  596.              if(!strncmp(p,"-xref"   ,5)) {option_warn|=WARN_XREF   ; p=&p[5]; continue;}
  597.              break;
  598.             }
  599.        if(is_argv) args[i]=NULL;
  600.        continue;
  601.       }
  602.  
  603.     if(!strncmp(args[i],"-index",6))
  604.       {
  605.        char* p=&args[i][6];
  606.  
  607.        if(!*p)
  608.           option_index=INDEX_ALL;
  609.        else
  610.           while(*p)
  611.             {
  612.              if(!strncmp(p,"-all" ,4)) {option_index|=INDEX_ALL ; p=&p[4]; continue;}
  613.              if(!strncmp(p,"-file",5)) {option_index|=INDEX_FILE; p=&p[5]; continue;}
  614.              if(!strncmp(p,"-func",5)) {option_index|=INDEX_FUNC; p=&p[5]; continue;}
  615.              if(!strncmp(p,"-var" ,4)) {option_index|=INDEX_VAR ; p=&p[4]; continue;}
  616.              if(!strncmp(p,"-type",5)) {option_index|=INDEX_TYPE; p=&p[5]; continue;}
  617.              break;
  618.             }
  619.        if(is_argv) args[i]=NULL;
  620.        continue;
  621.       }
  622.  
  623.     if(!strcmp(args[i],"-raw"))
  624.       {option_raw=1; if(is_argv)args[i]=NULL; continue;}
  625.  
  626.     if(!strcmp(args[i],"-latex"))
  627.       {option_latex=1; if(is_argv)args[i]=NULL; continue;}
  628.     if(!strcmp(args[i],"-latex2e"))
  629.       {option_latex=2; if(is_argv)args[i]=NULL; continue;}
  630.  
  631.     if(!strcmp(args[i],"-html"))
  632.       {option_html=1; if(is_argv)args[i]=NULL; continue;}
  633.  
  634.     if(!strcmp(args[i],"--"))
  635.       {end_of_args=1; if(is_argv)args[i]=NULL; continue;}
  636.  
  637.     if(args[i][0]=='-')
  638.       {fprintf(stderr,"cxref: Unknown option '%s'.\n",args[i]);return(1);}
  639.  
  640.     if(!is_argv)
  641.       {fprintf(stderr,"cxref: File names '%s' only allowed on command line.\n",args[i]);return(1);}
  642.    }
  643.  
  644.  if(option_warn&WARN_XREF && !option_xref)
  645.     fprintf(stderr,"cxref: Warning using '-warn-xref' without '-xref'.\n");
  646.  
  647.  return(0);
  648. }
  649.  
  650.  
  651. /*++++++++++++++++++++++++++++++++++++++
  652.   Canonicalise a file name by removing '/../', '/./' and '//' references.
  653.  
  654.   char *CanonicaliseName Returns the argument modified.
  655.  
  656.   char *name The original name
  657.   ++++++++++++++++++++++++++++++++++++++*/
  658.  
  659. char *CanonicaliseName(char *name)
  660. {
  661.  char *match;
  662.  
  663.  while((match=strstr(name,"/../")))
  664.    {
  665.     char *prev=match; match+=4;
  666.     while(prev>name && *--prev!='/');
  667.     if(prev!=name)prev++;
  668.     while((*prev++=*match++));
  669.    }
  670.  
  671.  while((match=strstr(name,"/./")) || (match=strstr(name,"./"))==name)
  672.    {
  673.     char *prev=match; match+=(*match=='/')?3:2;
  674.     while((*prev++=*match++));
  675.    }
  676.  
  677.  while((match=strstr(name,"//")))
  678.    {
  679.     char *prev=match; match+=2;
  680.     while((*prev++=*match++));
  681.    }
  682.  
  683.  match=&name[strlen(name)-2];
  684.  if(match>=name && !strcmp(match,"/."))
  685.     *match=0;
  686.  
  687.  match=&name[strlen(name)-3];
  688.  if(match>=name && !strcmp(match,"/.."))
  689.     if(match==name)
  690.        *match=0;
  691.     else
  692.        while(match>name && *--match!='/')
  693.           *match=0;
  694.  
  695.  return(name);
  696. }
  697.  
  698.  
  699. /*++++++++++++++++++++++++++++++++++++++
  700.   Calls CPP for the file to get all of the needed information.
  701.  
  702.   int DocumentTheFile Returns 1 in case of error, else 0.
  703.  
  704.   char* name The name of the file to document.
  705.  
  706.   The CPP is started as a sub-process, (using popen to return a FILE* for lex to use).
  707.   ++++++++++++++++++++++++++++++++++++++*/
  708.  
  709. static int DocumentTheFile(char* name)
  710. {
  711.  struct stat stat_buf;
  712.  int error1,error2;
  713.  
  714.  if(stat(name,&stat_buf)==-1)
  715.    {fprintf(stderr,"cxref: Cannot access the file '%s'\n",name);return(1);}
  716.  
  717.  #ifdef AMIGA /* olsen */
  718.  {
  719.    printf("Documenting \"%s\"...\n",name);
  720.  }
  721.  #endif /* AMIGA */
  722.  
  723.  cpp_command[cpp_command_num  ]=name;
  724.  cpp_command[cpp_command_num+1]=NULL;
  725.  
  726.  yyin=popen_execvp(cpp_command);
  727.  
  728.  if(!yyin)
  729.    {fprintf(stderr,"cxref: Failed to start the cpp command\n");exit(1);}
  730.  
  731.  yyrestart(yyin);
  732.  
  733. #if YYDEBUG
  734.  yydebug=(YYDEBUG==3);
  735. #endif
  736.  
  737.  error1=yyparse();
  738.  
  739.  error2=pclose_execvp(yyin);
  740.  
  741.  #ifdef AMIGA /* olsen */
  742.  {
  743.    /* Perform garbage collection for the parser. */
  744.    alloca(0);
  745.  }
  746.  #endif /* AMIGA */
  747.  
  748.  if(error2)
  749.     fprintf(stderr,"cxref: The preprocessor exited abnormally on '%s'\n",name);
  750.  
  751.  return(error1||error2);
  752. }
  753.  
  754. #ifndef AMIGA /* olsen */
  755. /*+ The process id of the pre-processor. +*/
  756. static int popen_pid;
  757.  
  758. /*++++++++++++++++++++++++++++++++++++++
  759.   A popen function that takes a list of arguments not a string.
  760.  
  761.   FILE* popen_execvp Returns a file descriptor.
  762.  
  763.   char** command The command arguments.
  764.   ++++++++++++++++++++++++++++++++++++++*/
  765.  
  766. static FILE* popen_execvp(char** command)
  767. {
  768.  int fdr[2];
  769.  
  770.  if(pipe(fdr)==-1)
  771.    {fprintf(stderr,"cxref: Can not pipe for the cpp command.\n");exit(1);}
  772.  
  773.  if((popen_pid=fork())==-1)
  774.    {fprintf(stderr,"cxref: Can not fork for the cpp command.\n");exit(1);}
  775.  
  776.  if(popen_pid)                   /* The parent */
  777.    {
  778.     close(fdr[1]);
  779.    }
  780.  else                            /* The child */
  781.    {
  782.     close(1);
  783.     dup(fdr[1]);
  784.     close(fdr[1]);
  785.  
  786.     close(fdr[0]);
  787.  
  788.     execvp(command[0],command);
  789.     fprintf(stderr,"cxref: Can not execvp for the cpp command.\n");
  790.     exit(1);
  791.    }
  792.  
  793.  return(fdopen(fdr[0],"r"));
  794. }
  795.  
  796.  
  797. /*++++++++++++++++++++++++++++++++++++++
  798.   Close the file to the to the preprocessor
  799.  
  800.   int pclose_execvp Return the error status.
  801.  
  802.   FILE* f The file to close.
  803.   ++++++++++++++++++++++++++++++++++++++*/
  804.  
  805. static int pclose_execvp(FILE* f)
  806. {
  807.  int ret;
  808.  
  809.  waitpid(popen_pid,&ret,0);
  810.  fclose(f);
  811.  
  812.  return(ret);
  813. }
  814. #endif /* AMIGA */
  815.