home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / prog_c / ansi.lzh / ansi.c next >
Encoding:
C/C++ Source or Header  |  1992-02-01  |  30.8 KB  |  1,056 lines

  1. /***************************************************************************
  2.  
  3.    Program:    ansi
  4.    File:       ansi.c
  5.    
  6.    Version:    V1.0
  7.    Date:       16.12.91
  8.    Function:   Convert C source to and from ANSI form.
  9.    
  10.    Copyright:  SciTech Software 1991
  11.    Author:     Andrew C. R. Martin
  12.    Address:    SciTech Software
  13.                23, Stag Leys,
  14.                Ashtead,
  15.                Surrey,
  16.                KT21 2TD.
  17.    Phone:      +44 (0372) 275775
  18.    EMail:      UUCP: cbmuk!cbmuka!scitec!amartin
  19.                JANET: andrew@uk.ac.ox.biop
  20.                
  21. ****************************************************************************
  22.  
  23.    This program is not in the public domain, but it may be freely copied
  24.    and distributed for no charge providing this header is included.
  25.    The code may be modified as required, but any modifications must be
  26.    documented so that the person responsible can be identified. If someone
  27.    else breaks this code, I don't want to be blamed for code that does not
  28.    work! The code may not be sold commercially without prior permission from
  29.    the author, although it may be given away free with commercial products,
  30.    providing it is made clear that this program is free and that the source
  31.    code is provided with the program.
  32.  
  33. ****************************************************************************
  34.  
  35.    Description:
  36.    ============
  37.  
  38.    This program alters function definitions to convert non-ANSI C code to 
  39.    ANSI form. The -k and -p flags allow conversion from ANSI to K&R and
  40.    generation of prototypes respectively.
  41.    
  42.    There are two *minor* problems:
  43.    1. In generation of prototypes. If a function has been defined with no 
  44.    explicit type it defaults to being int. Strictly the prototype should 
  45.    explicitly state this is int, but doesn't.
  46.    2. If a conversion actually occurs (either to or from ANSI) any comments
  47.    which were in the definition will be lost.
  48.    
  49.    The only restriction (that I can think of!) on the code being processed
  50.    is that a function definition must be the first thing on a line.
  51.    i.e. if a comment is placed on the same line as the definition but before
  52.    it, the program will think the whole line is a comment.
  53.    
  54. ****************************************************************************
  55.  
  56.    Usage:
  57.    ======
  58.  
  59.    ansi [-k -p] <in.c> <out.c>
  60.          -k generates K&R form code from ANSI
  61.          -p generates a set of prototypes
  62.  
  63. ****************************************************************************
  64.  
  65.    Revision History:
  66.    =================
  67.    
  68.    V1.0  17.12.91
  69.    Added support for prototype and K&R code generation. Also reorganised 
  70.    some code.
  71.    
  72. ***************************************************************************/
  73. /* System includes
  74. */
  75. #include <stdio.h>
  76. #include <string.h>
  77.  
  78. #ifdef AMIGA
  79. #include <exec/types.h>
  80.  
  81. #else /* Not an Amiga */
  82. typedef short BOOL;
  83. #ifndef TRUE
  84. #define TRUE  1
  85. #define FALSE 0
  86. #endif
  87. #endif
  88.  
  89. /**************************************************************************/
  90. #define MAXBUFF      200   /* Max chars in a line                         */
  91. #define MAXLINES     50    /* Max lines in a function definition          */
  92. #define DIC          34    /* Double inverted commas                      */
  93. #define SIC          39    /* Single inverted commas                      */
  94. #define LF           10    /* Line feed                                   */
  95. #define CR           13    /* Carriage return                             */
  96. #define MakeANSI     1     /* K&R-->ANSI                                  */
  97. #define MakeKR       2     /* ANSI-->K&R                                  */
  98. #define MakeProtos   3     /* Make prototypes                             */
  99.  
  100. #define toggle(x) (x) = abs((x)-1)
  101.  
  102. /**************************************************************************/
  103. /* Prototypes
  104. */
  105. int   main(int argc,
  106.            char **argv);
  107. int   GetVarName(char *buffer,
  108.                  char *strparam);
  109. void  process_file(FILE *fp_in,
  110.                    FILE *fp_out,
  111.                    int mode);
  112. int   isInteresting(char *buffer);
  113. void  Ansify(FILE *fp,
  114.              char funcdef[MAXLINES][MAXBUFF], 
  115.              int ndef,
  116.              int mode);
  117. void  WriteANSI(FILE *fp,
  118.                 char *varname,
  119.                 char *definitions);
  120. char  *FindString(char *buffer,
  121.                   char *string);
  122. int   isFunc(char funcdef[MAXLINES][MAXBUFF], 
  123.             int ndef);
  124. void  terminate(char *string);
  125. void  DeAnsify(FILE *fp_out, 
  126.                char funcdef[MAXLINES][MAXBUFF], 
  127.                int  ndef);
  128. void WriteKR(FILE *fp,
  129.              char *varname,
  130.              char *definitions);
  131. /**************************************************************************/
  132. main(int  argc,
  133.      char **argv)
  134. {
  135.    int   mode        = MakeANSI;
  136.    BOOL  noisy       = TRUE;
  137.    FILE  *fp_in      = NULL,
  138.          *fp_out     = NULL;
  139.    
  140.    if(argc < 3)
  141.    {
  142.       printf("\nUsage: ansi [-k -p -q] <in.c> <out.c>\n");
  143.       printf("       Converts a K&R style C file to ANSI or vice versa\n");
  144.       printf("          -k generates K&R form code from ANSI\n");
  145.       printf("          -p generates a set of prototypes\n");
  146.       printf("          -q quiet mode\n\n");
  147.       
  148.       exit(0);
  149.    }
  150.    
  151.    /* Parse the command line */
  152.    argv++;
  153.    while(--argc > 2)
  154.    {
  155.       if(argv[0][0] == '-')
  156.       {
  157.          switch(argv[0][1])
  158.          {
  159.          case 'k':
  160.          case 'K':
  161.             mode = MakeKR;
  162.             break;
  163.          case 'p':
  164.          case 'P':
  165.             mode = MakeProtos;
  166.             break;
  167.          case 'q':
  168.          case 'Q':
  169.             noisy = FALSE;
  170.             break;
  171.          default:
  172.             printf("Unknown switch %s\n",argv[0]);
  173.             exit(0);
  174.          }
  175.       }
  176.       else
  177.       {
  178.          printf("Invalid switch %s\n",argv[0]);
  179.          exit(0);
  180.       }
  181.       argv++;
  182.    }
  183.    
  184.    /* Open files */
  185.    if((fp_in = fopen(argv[0],"r")) == NULL)
  186.    {
  187.       printf("Unable to open input file %s\n",argv[0]);
  188.       exit(1);
  189.    }
  190.    if((fp_out = fopen(argv[1],"w")) == NULL)
  191.    {
  192.       printf("Unable to open output file %s\n",argv[1]);
  193.       exit(1);
  194.    }
  195.  
  196.    /* Give a message */
  197.    if(noisy)
  198.    {
  199.       printf("SciTech Software ansi C converter\n");
  200.       printf("Copyright (C) 1991 SciTech Software. All Rights Reserved.\n");
  201.       printf("This program is freely distributable providing no profit is made in so doing.\n\n");
  202.       switch(mode)
  203.       {
  204.       case MakeANSI:
  205.          printf("Converting file %s to ANSI\n",argv[0]);
  206.          break;
  207.       case MakeKR:
  208.          printf("Converting file %s to Kernighan and Ritchie\n",argv[0]);
  209.          break;
  210.       case MakeProtos:
  211.          printf("Generating prototypes for file %s\n",argv[0]);
  212.          break;
  213.       default:
  214.          break;
  215.       }
  216.    }
  217.  
  218.    /* Now process the files as required by the flags */
  219.    process_file(fp_in, fp_out, mode);
  220.    
  221.    return(0);
  222. }
  223.  
  224. /************************************************************************
  225. GetVarName(buffer, strparam)
  226. ----------------------------
  227. Input:   char     *buffer        A character string
  228. Output:  char     *strparam      Returned character string
  229. Returns: int                     Number of characters pulled out
  230.                                  of the buffer string
  231.  
  232. This routine returns the first , or ) delimited group of characters
  233. from character string `buffer'
  234. *************************************************************************/
  235. int GetVarName(char *buffer,
  236.                char *strparam)
  237. {
  238.    int   i,
  239.          j  = 0;
  240.  
  241.    for(i=0;buffer[i];i++)
  242.    {
  243.       /* Break out if we've got a , or ) */
  244.       if(buffer[i]==',' || buffer[i]==')') break;
  245.  
  246.       /* Otherwise copy the character */
  247.       strparam[j++] = buffer[i];
  248.    }
  249.    strparam[j]='\0';
  250.    
  251.    /* Strip any trailing spaces */
  252.    for(j=strlen(strparam) - 1 ;
  253.        j >= 0 && (strparam[j] == ' ' || strparam[j] == '\t');
  254.        j--)
  255.       strparam[j] = '\0';
  256.  
  257.    return(i);
  258. }
  259.  
  260.  
  261. /***************************************************************************
  262. process_file(fp_in, fp_out, mode)
  263. ---------------------------------
  264. Input:   FILE     *fp_in         File to be processed
  265.          FILE     *fp_out        Output file being created
  266.          int      mode           Processing mode.
  267.                                  MakeANSI:   Create ANSI
  268.                                  MakeKR:     Create K&R
  269.                                  MakeProtos: Create prototypes
  270. Returns: void
  271.  
  272. Does the work of processing the file
  273. ***************************************************************************/
  274. void process_file(FILE *fp_in,
  275.                   FILE *fp_out,
  276.                   int mode)
  277. {
  278.    /* These are static so they're not placed on the stack. This lets
  279.       us run with the default stack size on the Amiga
  280.    */
  281.    static char buffer[MAXBUFF],
  282.                funcdef[MAXLINES][MAXBUFF];
  283.    int  i,
  284.         ndef;
  285.    
  286.    while(fgets(buffer,MAXBUFF,fp_in))
  287.    {
  288.       terminate(buffer);
  289.  
  290.       /* See if this line is possibly a function definition */
  291.       if(isInteresting(buffer))
  292.       {
  293.          /* It's one of:
  294.             (a)   A function definition
  295.             (b)   A prototype
  296.             (c)   An external
  297.             
  298.             To be a function, it must contain a (, though this could be
  299.             a prototype.
  300.          */
  301.          
  302.          if(strchr(buffer,'(') != NULL)
  303.          {
  304.             /* It's a function or a prototype. Copy it into funcdef
  305.                assembling additional strings up to the first ; or {
  306.             */
  307.             strcpy(funcdef[0], buffer);
  308.             ndef=0;
  309.             while(strchr(funcdef[ndef],';') == NULL  &&
  310.                   strchr(funcdef[ndef],'{') == NULL)
  311.             {
  312.                if(!fgets(funcdef[++ndef],MAXBUFF,fp_in)) break;
  313.                if(ndef >= MAXLINES)
  314.                {
  315.                   printf("Too many lines in function definition\n");
  316.                   exit(1);
  317.                }
  318.                terminate(funcdef[ndef]);
  319.                /* Pass the string to isInteresting() to update internal
  320.                   count of comments, brackets, etc. We don't care about
  321.                   the return value.
  322.                */
  323.                isInteresting(funcdef[ndef]);
  324.             }
  325.  
  326.             if(isFunc(funcdef,ndef))
  327.             {
  328.                /* It's actually a function.
  329.                   If it was terminated by a ; we must assemble up to
  330.                   a {
  331.                */
  332.                if(strchr(funcdef[ndef],';') != NULL  &&
  333.                   strchr(funcdef[ndef],'{') == NULL)
  334.                {
  335.                   while(strchr(funcdef[ndef],'{') == NULL)
  336.                   {
  337.                      if(!fgets(funcdef[++ndef],MAXBUFF,fp_in)) break;
  338.                      if(ndef >= MAXLINES)
  339.                      {
  340.                         printf("Too many lines in function definition\n");
  341.                         exit(1);
  342.                      }
  343.                      terminate(funcdef[ndef]);
  344.                      /* Pass the string to isInteresting() to update 
  345.                         internal count of comments, brackets, etc. We 
  346.                         don't care about the return value.
  347.                      */
  348.                      isInteresting(funcdef[ndef]);
  349.                   }
  350.                }
  351.                
  352.                /* Now actually ANSIfy, deANSIfy, or generate prototypes.
  353.                   Output to fp_out
  354.                */
  355.                switch(mode)
  356.                {
  357.                case MakeKR:
  358.                   DeAnsify(fp_out, funcdef, ndef);
  359.                   break;
  360.                case MakeANSI:
  361.                case MakeProtos:
  362.                   Ansify(fp_out, funcdef, ndef, mode);
  363.                   break;
  364.                default:
  365.                   printf("Internal confusion!!!\n");
  366.                   break;
  367.                }
  368.             }
  369.             else
  370.             {
  371.                /* It's a prototype, so copy each line out */
  372.                if(mode != MakeProtos)
  373.                {
  374.                   for(i=0; i<=ndef; i++)
  375.                      fprintf(fp_out,"%s\n",funcdef[i]);
  376.                }
  377.             }
  378.          }
  379.          else
  380.          {
  381.             /* It's an extern, so just copy it */
  382.             if(mode != MakeProtos) fprintf(fp_out,"%s\n",buffer);
  383.          }
  384.       }
  385.       else
  386.       {
  387.          /* We're in a #, comment, string, function or blank line.
  388.             Simply copy the line to the output file.
  389.          */
  390.          if(mode != MakeProtos) fprintf(fp_out,"%s\n",buffer);
  391.       }
  392.    }
  393. }
  394.  
  395. /***************************************************************************
  396. isInteresting(buffer)
  397. ---------------------
  398. Input:   char     *buffer        Line from file
  399. Returns: int                     1: Line is interesting-may be a function
  400.                                  0: Line not interesting
  401.  
  402. Tries to determine whether a line is possibly a function definition.
  403. ***************************************************************************/
  404. int isInteresting(char *buffer)
  405. {
  406.    static int  comment_count  = 0,
  407.                bra_count      = 0,
  408.                inSIC          = 0,
  409.                inDIC          = 0;
  410.    
  411.    int i,
  412.        retval  = 0,
  413.        isBlank = TRUE;
  414.  
  415.    /* Not interested if it's a #define, etc. */
  416.    if(buffer[0] == '#') return(0);
  417.  
  418.    /* If all of these are unset when we enter, we're interested */
  419.    if(!bra_count && !inDIC && !inSIC && !comment_count) retval = 1;
  420.  
  421.    /* If the first thing in this string was a comment we're no longer
  422.       interested.
  423.    */
  424.    for(i=0; buffer[i] && (buffer[i] == ' ' || buffer[i] == '\t'); i++);
  425.    if(buffer[i] == '/' && buffer[i+1] == '*') retval = 0;
  426.  
  427.    /* Step along the line */
  428.    for(i=0; i<strlen(buffer); i++)
  429.    {
  430.       /* We're not interested in anything else if this is a
  431.          C++ style comment
  432.       */
  433.       if(buffer[i] == '/' && buffer[i+1] == '/') return(0);
  434.  
  435.       if(buffer[i] != ' ' && buffer[i] != '\t') isBlank = FALSE;
  436.       
  437.       /* See if we're moving into a string */
  438.       if((buffer[i] == DIC) && (comment_count==0) && !inSIC) toggle(inDIC);
  439.       if((buffer[i] == SIC) && (comment_count==0) && !inDIC) 
  440.       {
  441.          toggle(inSIC);
  442.       }
  443.       
  444.       /* If we're not in a string */
  445.       if(!inDIC && !inSIC)
  446.       {
  447.          /* See if we're moving into a comment */
  448.          if((buffer[i] == '/') && (buffer[i+1] == '*')) comment_count++;
  449.          /* See if we're moving out of a comment */
  450.          if((buffer[i] == '*') && (buffer[i+1] == '/')) comment_count--;
  451.          
  452.          /* If we're not in a comment we must be in code.
  453.             Update the curly bracket count
  454.          */
  455.          if(!comment_count)
  456.          {
  457.             if(buffer[i] == '{') bra_count++;
  458.             if(buffer[i] == '}') bra_count--;
  459.          }
  460.       }
  461.    }
  462.    
  463.    /* If it's a blank line, we're not interested */
  464.    if(isBlank) retval = 0;
  465.  
  466.    return(retval);
  467. }
  468.          
  469.  
  470. /***************************************************************************
  471. Ansify(fp, funcdef, ndef, mode)
  472. -------------------------------
  473. Input:   FILE     *fp            File to create
  474.          char     funcdef[][]    Function definition lines
  475.          int      ndef           Number of definition lines
  476.          int      mode           Processing mode-generate ANSI or prototypes
  477.                                  MakeANSI:   Create ANSI
  478.                                  MakeProtos: Create prototypes
  479. ***************************************************************************/
  480. void Ansify(FILE *fp,
  481.             char funcdef[MAXLINES][MAXBUFF],
  482.             int  ndef,
  483.             int  mode)
  484. {
  485.    int   i,
  486.          j,
  487.          width,
  488.          isANSI   = TRUE,
  489.          bufflen  = 0,
  490.          first    = TRUE;
  491.    char  *buffer  = NULL,
  492.          *bufptr,
  493.          *funptr,
  494.          temp[MAXBUFF],
  495.          func[MAXBUFF],
  496.          varname[80];
  497.    
  498.    ndef++;
  499.    
  500.    /* If none of the lines contains a ;, it's already ANSI */
  501.    for(i=0; i<ndef; i++)
  502.    {
  503.       if(strchr(funcdef[i], ';') != NULL)
  504.       {
  505.          isANSI = FALSE;
  506.          break;
  507.       }
  508.    }
  509.    
  510.    if(isANSI)
  511.    {
  512.       /* It's already ANSI */
  513.       if(mode == MakeANSI)
  514.       {
  515.          /* We're making ANSI, so just output it */
  516.          for(i=0; i<ndef; i++) fprintf(fp, "%s\n", funcdef[i]);
  517.       }
  518.       else  /* mode == makeProtos */
  519.       {
  520.          /* We're making prototypes, just output, but put a ; instead
  521.             of a {
  522.          */
  523.          for(i=0; i<ndef; i++)
  524.          {
  525.             for(j=0; j<strlen(funcdef[i]); j++)
  526.             {
  527.                if(funcdef[i][j] != '{')
  528.                {
  529.                   putc(funcdef[i][j], fp);
  530.                }
  531.                else
  532.                {
  533.                   putc(';', fp);
  534.                   i = ndef;
  535.                   break;
  536.                }
  537.             }
  538.             putc('\n', fp);
  539.          }
  540.       }
  541.    }
  542.    else     /* It's not ANSI, so we convert it. */
  543.    {
  544.       /* First allocate some memory */
  545.       for(i=0; i<ndef; i++) bufflen += strlen(funcdef[i]);
  546.       bufflen += 2;
  547.       buffer = (char *)malloc(bufflen * sizeof(char));
  548.       buffer[0] = '\0';
  549.       
  550.       /* Now build all the strings into the single buffer */
  551.       for(i=0; i<ndef; i++) strcat(buffer, funcdef[i]);
  552.  
  553.       /* Copy the function part int func */
  554.       for(i=0; buffer[i] != ')'; i++) func[i] = buffer[i];
  555.       func[i]     = ')';
  556.       func[i+1]   = '\0';
  557.       
  558.       /* Find the first (, copy up to here and print it */
  559.       for(i=0; func[i] != '('; i++) temp[i] = func[i];
  560.       temp[i]     = '(';
  561.       temp[i+1]   = '\0';
  562.       width       = strlen(temp);
  563.       fprintf(fp,"%s",temp);
  564.       
  565.       /* Set bufptr to point to the buffer excluding the function def */
  566.       bufptr = strchr(buffer, ')') + 1;
  567.       
  568.       /* Set funptr to point to start of parameter list */
  569.       funptr = strchr(func, '(') + 1;
  570.       
  571.       /* Step through the parameter list getting a parameter at a time */
  572.       first = TRUE;
  573.       while(*funptr && *funptr != ')')
  574.       {
  575.          if(!first)
  576.          {
  577.             fprintf(fp,",\n");
  578.             for(i=0;i<width;i++) fprintf(fp," ");
  579.          }
  580.          first = FALSE;
  581.          /* Kill spaces */
  582.          for( ; funptr && (*funptr == ' ' || *funptr == '\t'); funptr++) ;
  583.          /* Get a parameter */
  584.          funptr += GetVarName(funptr, varname) + 1;
  585.          /* Write the ANSI version */
  586.          WriteANSI(fp, varname, bufptr);
  587.       }
  588.       
  589.       if(mode == MakeANSI)
  590.          fprintf(fp,")\n{\n");
  591.       else  /* mode == MakeProtos */
  592.          fprintf(fp,");\n");
  593.       
  594.       /* Free memory */
  595.       free(buffer);
  596.    }
  597. }
  598.  
  599. /***************************************************************************
  600. WriteANSI(fp, varname, definitions)
  601. -----------------------------------
  602. Input:   FILE     *fp            File being written
  603.          char     *varname       Variable name being processed
  604.          char     *definitions   Assembled KR definitions.
  605. Returns: void         
  606.  
  607. Creates an ANSI definition from the KR definition and places it in the
  608. parameter list.
  609. ***************************************************************************/
  610. void WriteANSI(FILE *fp,
  611.                char *varname,
  612.                char *definitions)
  613. {
  614.    char  *start,
  615.          *stop,
  616.          *ptr,
  617.          buffer[MAXBUFF];
  618.    int   i;
  619.         
  620. /*** Find the variable type ***/
  621.  
  622.    /* Set these to the position of varname in the definitions list */
  623.    start = stop = FindString(definitions, varname);
  624.    
  625.    if(!start)
  626.    {
  627.       printf("Parameter %s was not found in definitions\n",varname);
  628.       return ;
  629.    }
  630.    
  631.    /* Step start back to the start of the list, the preceeding ; or / */
  632.    while(start > definitions && *start != ';' && *start != '/') start--;
  633.    if(*start == ';' || *start == '/') start++;
  634.    
  635.    /* Kill any leading spaces */
  636.    while(*start && (*start == ' ' || *start == '\t')) start++;
  637.    
  638.    /* If there are any commas between start and stop, move stop
  639.       back to the first comma
  640.    */
  641.    for(ptr=start; ptr<=stop; ptr++)
  642.    {
  643.       if(*ptr == ',')
  644.       {
  645.          stop = ptr;
  646.          break;
  647.       }
  648.    }
  649.    
  650.    /* Step stop on to the first , or ; */
  651.    while(*stop && *stop != ',' && *stop != ';') stop++;
  652.  
  653.    /* Now step back over any spaces */
  654.    stop--;
  655.    while(stop > start && (*stop == ' ' || *stop == '\t')) stop--;
  656.    
  657.    /* Now step back over the first variable name */
  658.    while(stop > start && *stop != ' ' && *stop != '\t') stop--;
  659.    
  660.    /* and over the spaces preceeding it */
  661.    while(stop > start && (*stop == ' ' || *stop == '\t')) stop--;
  662.    
  663.    /* Now copy the string delimited by start and stop */
  664.    for(i=0; i<MAXBUFF && start <= stop; i++, start++)
  665.       buffer[i] = *start;
  666.  
  667.    /* Terminate and print it */
  668.    buffer[i] = '\0';
  669.    fprintf(fp,"%s ",buffer);
  670.    
  671. /*** Now print the variable name with *'s if appropriate ***/
  672.  
  673.    /* Set this to the position of varname in the definitions list */
  674.    start = FindString(definitions, varname);
  675.    
  676.    /* Step start back to the first non-space character */
  677.    start--;
  678.    while(start > definitions && (*start == ' ' || *start == '\t')) start--;
  679.    
  680.    while(*(start--) == '*')
  681.       fprintf(fp,"*");
  682.  
  683.    fprintf(fp,"%s",varname);
  684.    
  685. /*** Finally see if it's a [] array ***/
  686.    /* Set these to the position of varname in the definitions list */
  687.    start = stop = FindString(definitions, varname);
  688.  
  689.    /* Step stop on to the first , or ; */
  690.    while(*stop && *stop != ',' && *stop != ';') stop++;
  691.  
  692.    /* Now step back over any spaces */
  693.    stop--;
  694.    while(stop > start && (*stop == ' ' || *stop == '\t')) stop--;
  695.    
  696.    /* See if there is a [ between start and stop */
  697.    while(start<stop && *start != '[') start++;
  698.    
  699.    /* If a [ was found copy and print the string */
  700.    if(start < stop)
  701.    {
  702.       for(i=0; i<MAXBUFF && start <= stop; i++, start++)
  703.          buffer[i] = *start;
  704.  
  705.       /* Terminate and print it */
  706.       buffer[i] = '\0';
  707.       fprintf(fp,"%s",buffer);
  708.    }
  709. }
  710.  
  711. /***************************************************************************
  712. FindString(buffer, string)
  713. --------------------------
  714. Input:   char     *buffer        Buffer being searched
  715.          char     *string        String to search for
  716. Returns: *char                   Pointer to start of string in buffer
  717.  
  718. Searches for a string in another string returning a pointer to the start
  719. of the string.
  720. ***************************************************************************/
  721. char *FindString(char *buffer,
  722.                  char *string)
  723. {
  724.    char  *ptr;
  725.    int   ok = FALSE,
  726.          i;
  727.    
  728.    ptr = buffer;
  729.    
  730.    while(!ok)
  731.    {
  732.       /* Step ptr along buffer till we find first character of string */
  733.       while(*ptr && *ptr != *string) ptr++;
  734.  
  735.       /* Return NULL if we didn't find it */
  736.       if(*ptr == '\0') return((char *)NULL);
  737.       
  738.       /* Now compare the rest of the string */
  739.       ok = TRUE;
  740.       for(i=0; i<strlen(string); i++)
  741.       {
  742.          if(ptr[i] != string[i])
  743.          {
  744.             ok = FALSE;
  745.             break;
  746.          }
  747.       }
  748.       ptr++;
  749.    }
  750.    return(--ptr);
  751. }
  752. /***************************************************************************
  753. isFunc(funcdef, ndef)
  754. ---------------------
  755. Input:   char     funcdef[][]    Array of lines forming function definition
  756.          int      ndef           Number of lines
  757. Returns: int                     1: This is a function
  758.                                  0: Not a function
  759.  
  760. Determines whether a possible function definition identified by 
  761. isInteresting() really is a function.
  762. ***************************************************************************/
  763. int isFunc(char funcdef[MAXLINES][MAXBUFF],
  764.            int  ndef)
  765. {
  766.    char  *termchar;
  767.    int   line,
  768.          retval;
  769.    
  770.    /* If it's a prototype, it will not be terminated by a { */
  771.    if(strchr(funcdef[ndef],'{') != NULL) return(1);
  772.    
  773.    /* It's now either a prototype or a K&R function defintion.
  774.       To be a prototype, the first non-space character before the
  775.       ; must be a )
  776.       
  777.       Step backwards.
  778.    */
  779.    line = ndef;
  780.    for(;;)
  781.    {
  782.       termchar = strchr(funcdef[line],';') - 1;
  783.       while(termchar >= funcdef[line] && 
  784.             (*termchar == ' ' || *termchar == '\t'))
  785.          termchar--;
  786.       
  787.       /* If we stepped back beyond the start of the line, go to the
  788.          previous line
  789.       */
  790.       if(termchar < funcdef[line])
  791.       {
  792.          line--;
  793.          if(line < 0) break;
  794.          termchar = funcdef[line] + strlen(funcdef[line]);
  795.       }
  796.       else
  797.       {
  798.          break;
  799.       }
  800.    }
  801.    
  802.    /* OK, see if the character was a ) */
  803.    if(*termchar == ')')
  804.       retval = 0;
  805.    else
  806.       retval = 1;
  807.       
  808.    return(retval);
  809. }
  810.  
  811. /*************************************************************************
  812. terminate(string)
  813. -----------------
  814. I/O:     char     *string        A character string
  815. Returns: void
  816.  
  817. Terminates a string at the first \n
  818. *************************************************************************/
  819. void terminate(char *string)
  820. {
  821.    int i;
  822.    
  823.    for(i=0;string[i];i++)
  824.    {
  825.       if(string[i] == '\n')
  826.       {
  827.          string[i] = '\0';
  828.          break;
  829.       }
  830.    }
  831. }
  832. /*************************************************************************
  833. DeAnsify(fp, funcdef, ndef)
  834. ---------------------------
  835. Input:   FILE     *fp            File being written
  836.          char     funcdef[][]    Function definition array
  837.          int      ndef           Number of definition lines
  838. Returns: void
  839.  
  840. Writes a K&R function definition from the ANSI (or K&R) form in funcdef.
  841. *************************************************************************/
  842. void DeAnsify(FILE *fp, 
  843.               char funcdef[MAXLINES][MAXBUFF], 
  844.               int  ndef)
  845. {
  846.    int   i,
  847.          j,
  848.          nparam,
  849.          isKR     = FALSE,
  850.          bufflen  = 0,
  851.          last     = FALSE;
  852.    char  *buffer  = NULL,
  853.          *bufptr,
  854.          *funptr,
  855.          *ptr,
  856.          *start,
  857.          *stop,
  858.          temp[MAXBUFF],
  859.          func[MAXBUFF],
  860.          varname[80];
  861.    
  862.    ndef++;
  863.    
  864.    /* If any of the lines contains a ;, it's already KR */
  865.    for(i=0; i<ndef; i++)
  866.    {
  867.       if(strchr(funcdef[i], ';') != NULL)
  868.       {
  869.          isKR = TRUE;
  870.          break;
  871.       }
  872.    }
  873.    
  874.    if(isKR)
  875.    {
  876.       /* It's already KR, so just output it */
  877.       for(i=0; i<ndef; i++) fprintf(fp, "%s\n", funcdef[i]);
  878.    }
  879.    else     /* It's not KR, so we convert it. */
  880.    {
  881.       /* First allocate some memory */
  882.       for(i=0; i<ndef; i++) bufflen += strlen(funcdef[i]);
  883.       bufflen += 2;
  884.       buffer = (char *)malloc(bufflen * sizeof(char));
  885.       buffer[0] = '\0';
  886.       
  887.       /* Now build all the strings into the single buffer ignoring comments */
  888.       for(i=0; i<ndef; i++) strcat(buffer,funcdef[i]);
  889.  
  890.       /* Find the first (, copy up to here and print it */
  891.       for(i=0; buffer[i] != '('; i++) temp[i] = buffer[i];
  892.       temp[i]     = '(';
  893.       temp[i+1]   = '\0';
  894.       fprintf(fp,"%s",temp);
  895.       
  896.       /* Set bufptr to point to the buffer excluding the function name */
  897.       bufptr = strchr(buffer, '(') + 1;
  898.       
  899.       /* Count the number of commas in the parameter list */
  900.       nparam = 0;
  901.       for(funptr = bufptr; *funptr && *funptr != ')'; funptr++)
  902.          if(*funptr == ',') nparam++;
  903.          
  904.       if(nparam)
  905.       {
  906.          /* If there were *any* commas, the number of parameters is one
  907.             more than the number of commas
  908.          */
  909.          nparam++;
  910.       }
  911.       else
  912.       {
  913.          /* If there weren't any commas, there are either 0 or 1 params.
  914.             If there's only white space, or `void' between the ( and ) 
  915.             there are 0 parameters. Otherwise, there's 1
  916.          */
  917.          if(FindString(bufptr,"void") || FindString(bufptr,"VOID"))
  918.          {
  919.             nparam = 0;
  920.          }
  921.          else
  922.          {
  923.             for(funptr = bufptr; *funptr && *funptr != ')'; funptr++)
  924.             {
  925.                if(*funptr != ' ' && *funptr != '\t')
  926.                {
  927.                   nparam = 1;
  928.                   break;
  929.                }
  930.             }
  931.          }
  932.       }
  933.       
  934.       /* If there weren't any parameters we can just output a closing
  935.          parenthesis an opening { and return.
  936.       */
  937.       if(nparam==0)
  938.       {
  939.          fprintf(fp,")\n{\n");
  940.          free(buffer);
  941.          return;
  942.       }
  943.  
  944.       /* Step through the parameter list getting a parameter at a time.
  945.          Assemble these into func.
  946.          The variable names are delimited by a , a [ or the closing )
  947.       */
  948.       func[0] = '\0';
  949.       funptr = bufptr;
  950.       for(i=0; i<nparam; i++)
  951.       {
  952.          /* Step funptr on to the next , or ) */
  953.          if((funptr = strchr(funptr,',')) == NULL)
  954.          {
  955.             funptr = strchr(bufptr,')');
  956.             last = TRUE;
  957.          }
  958.          
  959.          /* Step back over any spaces */
  960.          stop = funptr-1;
  961.          while(stop>bufptr && (*stop==' ' || *stop=='\t')) stop--;
  962.          
  963.          /* Step back to the start of the variable name */
  964.          start = stop;
  965.          while(start>=bufptr && *start!=' ' && *start!='\t' && *start != '*')
  966.             start--;
  967.          start++;
  968.          
  969.          /* Copy the variable name into our function buffer adding 
  970.             a , and space or ) as appropriate.
  971.          */
  972.          for(j=0; start<=stop; start++, j++)
  973.             temp[j] = *start;
  974.          temp[j] = '\0';
  975.  
  976.          if((ptr = strchr(temp,'[')) != NULL)
  977.             *ptr = '\0';
  978.             
  979.          if(last)
  980.             strcat(temp,")");
  981.          else
  982.             strcat(temp,", ");
  983.          
  984.          strcat(func, temp);
  985.          funptr++;
  986.       }
  987.       
  988.       /* We can now echo the parameter list to the output file */
  989.       fprintf(fp,"%s\n",func);
  990.  
  991.       /* Work through the parameter list writing the parameter 
  992.          definition lines
  993.       */
  994.       funptr = func;
  995.       while(*funptr && *funptr != ')')
  996.       {
  997.          /* Kill spaces */
  998.          for( ; funptr && (*funptr == ' ' || *funptr == '\t'); funptr++) ;
  999.          /* Get a parameter */
  1000.          funptr += GetVarName(funptr, varname) + 1;
  1001.          /* Write the K&R version */
  1002.          WriteKR(fp, varname, bufptr);
  1003.       }
  1004.       
  1005.       fprintf(fp,"{\n");
  1006.  
  1007.       /* Free memory */
  1008.       free(buffer);
  1009.    }
  1010. }
  1011.  
  1012. /***************************************************************************
  1013. WriteKR(fp, varname, definitions)
  1014. ---------------------------------
  1015. Input:   FILE     *fp            File being written
  1016.          char     *varname       Variable being processed
  1017.          char     *definitions   ANSI style definitions
  1018. Returns: void
  1019.  
  1020. Writes a variable definition in K&R form by extracting information from
  1021. the ANSI definition.
  1022. ***************************************************************************/
  1023. void WriteKR(FILE *fp,
  1024.              char *varname,
  1025.              char *definitions)
  1026. {
  1027.    char  *start,
  1028.          *stop,
  1029.          temp[MAXBUFF];
  1030.    int   i;
  1031.    
  1032.    /* Find the variable name in the definitions */
  1033.    start = stop = FindString(definitions,varname);
  1034.    
  1035.    /* Step start back to the preceeding , / or (, then forward 
  1036.       over any spaces
  1037.    */
  1038.    while(start >= definitions && *start != '(' && 
  1039.          *start != ',' && *start != '/')
  1040.       start--;
  1041.    start++;
  1042.    while(start<stop && (*start==' ' || *start=='\t')) start++;
  1043.    
  1044.    /* Step stop on to the following , or ) */
  1045.    while(*stop && *stop != ')' && *stop != ',') stop++;
  1046.    stop--;
  1047.    
  1048.    /* Copy the variable definition, add a ; and output. */
  1049.    for(i=0; start<=stop; start++, i++)
  1050.       temp[i] = *start;
  1051.    temp[i]     = ';';
  1052.    temp[i+1]   = '\0';
  1053.  
  1054.    fprintf(fp,"%s\n",temp);
  1055. }
  1056.