home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
-
- Program: ansi
- File: ansi.c
-
- Version: V1.6
- Date: 16.12.91
- Function: Convert C source to and from ANSI form.
-
- Copyright: SciTech Software 1991
- Author: Andrew C. R. Martin
- Address: SciTech Software
- 23, Stag Leys,
- Ashtead,
- Surrey,
- KT21 2TD.
- Phone: +44 (0372) 275775
- EMail: UUCP: cbmuk!cbmuka!scitec!amartin
- JANET: andrew@uk.ac.ox.biop
-
- ****************************************************************************
-
- This program is not in the public domain, but it may be freely copied
- and distributed for no charge providing this header is included.
- The code may be modified as required, but any modifications must be
- documented so that the person responsible can be identified. If someone
- else breaks this code, I don't want to be blamed for code that does not
- work! The code may not be sold commercially without prior permission from
- the author, although it may be given away free with commercial products,
- providing it is made clear that this program is free and that the source
- code is provided with the program.
-
- ****************************************************************************
-
- Description:
- ============
-
- This program alters function definitions to convert non-ANSI C code to
- ANSI form. The -k and -p flags allow conversion from ANSI to K&R and
- generation of prototypes respectively.
-
- There are two *minor* problems:
- 1. In generation of prototypes. If a function has been defined with no
- explicit type it defaults to being int. Strictly the prototype should
- explicitly state this is int, but doesn't.
- 2. If a conversion actually occurs (either to or from ANSI) any comments
- which were in the definition will be lost.
-
- The only restriction (that I can think of!) on the code being processed
- is that a function definition must be the first thing on a line.
- i.e. if a comment is placed on the same line as the definition but before
- it, the program will think the whole line is a comment.
-
- ****************************************************************************
-
- Usage:
- ======
-
- ansi [-k -p] <in.c> <out.c>
- -k generates K&R form code from ANSI
- -p generates a set of prototypes
-
- ****************************************************************************
-
- Revision History:
- =================
-
- V1.0 17.12.91
- Added support for prototype and K&R code generation. Also reorganised
- some code.
-
- V1.1 21.01.92
- A little tidying for VAX and slightly more useful error messages when
- making ANSI and failing to find parameter definition---this spots bugs!
-
- V1.2 14.02.92
- Fixed a bug whereby variable names which were subsets of the associated
- type were not being found correctly.
- e.g. func(o,w) struct obs *o; struct wor *w; { }
- did not inherit *'s correctly in the ANSI version.
- Introduced FindVarName() for this purpose.
- Also added version string.
-
- V1.3 19.02.92
- Fixed reported bug in Ansify() where KR definitions containing
- comments between variables with a single type declaration were handled
- wrongly.
-
- V1.4 18.03.92
- Fixed bug reported by Bob Bruccoleri in process_file(). If a comment
- on the line of an external variable definition contained a (, the code
- would think this was a prototype definition and get very confused.
- Now kills the comments before testing for the presence of a (.
- Improved function definition comments.
-
- V1.5 26.03.92
- Fixed same bug as in V1.2, but for ANSI-->K&R; variable names, if a
- subset of a type name were getting picked up incorrectly.
-
- V1.6 01.04.92
- Small change to comments to work with my autodoc program.
-
- ***************************************************************************/
- /* System includes
- */
- #include <stdio.h>
- #include <string.h>
-
- #ifdef AMIGA
- #include <exec/types.h>
-
- #else /* Not an Amiga */
- typedef short BOOL;
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
- #endif
-
- /**************************************************************************/
- #define MAXBUFF 200 /* Max chars in a line */
- #define MAXLINES 50 /* Max lines in a function definition */
- #define DIC 34 /* Double inverted commas */
- #define SIC 39 /* Single inverted commas */
- #define LF 10 /* Line feed */
- #define CR 13 /* Carriage return */
- #define MakeANSI 1 /* K&R-->ANSI */
- #define MakeKR 2 /* ANSI-->K&R */
- #define MakeProtos 3 /* Make prototypes */
-
- #define toggle(x) (x) = abs((x)-1)
-
- /**************************************************************************/
- /* Prototypes
- */
- int main(int argc,
- char **argv);
- int GetVarName(char *buffer,
- char *strparam);
- void process_file(FILE *fp_in,
- FILE *fp_out,
- int mode);
- int isInteresting(char *buffer);
- void Ansify(FILE *fp,
- char funcdef[MAXLINES][MAXBUFF],
- int ndef,
- int mode);
- int WriteANSI(FILE *fp,
- char *varname,
- char *definitions);
- char *FindString(char *buffer,
- char *string);
- char *FindVarName(char *buffer,
- char *string);
- int isFunc(char funcdef[MAXLINES][MAXBUFF],
- int ndef);
- void terminate(char *string);
- void DeAnsify(FILE *fp_out,
- char funcdef[MAXLINES][MAXBUFF],
- int ndef);
- void WriteKR(FILE *fp,
- char *varname,
- char *definitions);
- void KillComments(char *buffer);
- /**************************************************************************/
- /* Version string
- */
- #ifdef AMIGA
- UBYTE *vers="\0$VER: ansi 1.5";
- #endif
-
- /**************************************************************************/
- main(int argc,
- char **argv)
- {
- int mode = MakeANSI;
- BOOL noisy = TRUE;
- FILE *fp_in = NULL,
- *fp_out = NULL;
-
- if(argc < 3)
- {
- printf("\nUsage: ansi [-k -p -q] <in.c> <out.c>\n");
- printf(" Converts a K&R style C file to ANSI or vice versa\n");
- printf(" -k generates K&R form code from ANSI\n");
- printf(" -p generates a set of prototypes\n");
- printf(" -q quiet mode\n\n");
-
- exit(0);
- }
-
- /* Parse the command line */
- argv++;
- while(--argc > 2)
- {
- if(argv[0][0] == '-')
- {
- switch(argv[0][1])
- {
- case 'k':
- case 'K':
- mode = MakeKR;
- break;
- case 'p':
- case 'P':
- mode = MakeProtos;
- break;
- case 'q':
- case 'Q':
- noisy = FALSE;
- break;
- default:
- printf("Unknown switch %s\n",argv[0]);
- exit(0);
- }
- }
- else
- {
- printf("Invalid switch %s\n",argv[0]);
- exit(0);
- }
- argv++;
- }
-
- /* Open files */
- if((fp_in = fopen(argv[0],"r")) == NULL)
- {
- printf("Unable to open input file %s\n",argv[0]);
- exit(1);
- }
- if((fp_out = fopen(argv[1],"w")) == NULL)
- {
- printf("Unable to open output file %s\n",argv[1]);
- exit(1);
- }
-
- /* Give a message */
- if(noisy)
- {
- printf("SciTech Software ansi C converter V1.5\n");
- printf("Copyright (C) 1991 SciTech Software. All Rights Reserved.\n");
- printf("This program is freely distributable providing no profit is made in so doing.\n\n");
- switch(mode)
- {
- case MakeANSI:
- printf("Converting file %s to ANSI\n",argv[0]);
- break;
- case MakeKR:
- printf("Converting file %s to Kernighan and Ritchie\n",argv[0]);
- break;
- case MakeProtos:
- printf("Generating prototypes for file %s\n",argv[0]);
- break;
- default:
- break;
- }
- }
-
- /* Now process the files as required by the flags */
- process_file(fp_in, fp_out, mode);
-
- exit(0); /* V1.1, for VAX clean-ness */
- return(0);
- }
-
- /*>**********************************************************************
- GetVarName(buffer, strparam)
- ----------------------------
- Input: char *buffer A character string
- Output: char *strparam Returned character string
- Returns: int Number of characters pulled out
- of the buffer string
-
- This routine returns the first , or ) delimited group of characters
- from character string `buffer'
- *************************************************************************/
- int GetVarName(char *buffer,
- char *strparam)
- {
- int i,
- j = 0;
-
- for(i=0;buffer[i];i++)
- {
- /* Break out if we've got a , or ) */
- if(buffer[i]==',' || buffer[i]==')') break;
-
- /* Otherwise copy the character */
- strparam[j++] = buffer[i];
- }
- strparam[j]='\0';
-
- /* Strip any trailing spaces */
- for(j=strlen(strparam) - 1 ;
- j >= 0 && (strparam[j] == ' ' || strparam[j] == '\t');
- j--)
- strparam[j] = '\0';
-
- return(i);
- }
-
-
- /*>*************************************************************************
- process_file(fp_in, fp_out, mode)
- ---------------------------------
- Input: FILE *fp_in File to be processed
- FILE *fp_out Output file being created
- int mode Processing mode.
- MakeANSI: Create ANSI
- MakeKR: Create K&R
- MakeProtos: Create prototypes
- Returns: void
-
- Does the work of processing the file. Calls routines to see if this line is
- interesting. If so assembles the function or prototype definition. Calls
- check to see if its really a function definition and, if so, routines to
- process and convert.
- ***************************************************************************/
- void process_file(FILE *fp_in,
- FILE *fp_out,
- int mode)
- {
- /* These are static so they're not placed on the stack. This lets
- us run with the default stack size on the Amiga
- */
- static char buffer[MAXBUFF],
- buffer2[MAXBUFF], /* V1.4 */
- funcdef[MAXLINES][MAXBUFF];
- int i,
- ndef;
-
- while(fgets(buffer,MAXBUFF,fp_in))
- {
- terminate(buffer);
-
- /* See if this line is possibly a function definition */
- if(isInteresting(buffer))
- {
- /* It's one of:
- (a) A function definition
- (b) A prototype
- (c) An external
-
- To be a function, it must contain a (, though this could be
- a prototype.
- */
-
- /* V1.4+: Previously would think the line was a function or
- prototype if there was a ( in a comment on the same line
- */
- strcpy(buffer2,buffer);
- KillComments(buffer2);
- /* V1.4- */
-
- if(strchr(buffer2,'(') != NULL) /* V1.4 Test buffer2 */
- {
- /* It's a function or a prototype. Copy it into funcdef
- assembling additional strings up to the first ; or {
- */
- strcpy(funcdef[0], buffer);
- ndef=0;
- while(strchr(funcdef[ndef],';') == NULL &&
- strchr(funcdef[ndef],'{') == NULL)
- {
- if(!fgets(funcdef[++ndef],MAXBUFF,fp_in)) break;
- terminate(funcdef[ndef]);
- if(ndef >= MAXLINES)
- {
- printf("Too many lines in function definition:\n");
- for(i=0; i<MAXLINES; i++)
- printf("%s\n",funcdef[i]);
- exit(1);
- }
- /* Pass the string to isInteresting() to update internal
- count of comments, brackets, etc. We don't care about
- the return value.
- */
- isInteresting(funcdef[ndef]);
- }
-
- if(isFunc(funcdef,ndef))
- {
- /* It's actually a function.
- If it was terminated by a ; we must assemble up to
- a {
- */
- if(strchr(funcdef[ndef],';') != NULL &&
- strchr(funcdef[ndef],'{') == NULL)
- {
- while(strchr(funcdef[ndef],'{') == NULL)
- {
- if(!fgets(funcdef[++ndef],MAXBUFF,fp_in)) break;
- if(ndef >= MAXLINES)
- {
- printf("Too many lines in function definition:\n");
- for(i=0; i<MAXLINES; i++)
- printf("%s\n",funcdef[i]);
- exit(1);
- }
- terminate(funcdef[ndef]);
- /* Pass the string to isInteresting() to update
- internal count of comments, brackets, etc. We
- don't care about the return value.
- */
- isInteresting(funcdef[ndef]);
- }
- }
-
- /* Now actually ANSIfy, deANSIfy, or generate prototypes.
- Output to fp_out
- */
- switch(mode)
- {
- case MakeKR:
- DeAnsify(fp_out, funcdef, ndef);
- break;
- case MakeANSI:
- case MakeProtos:
- Ansify(fp_out, funcdef, ndef, mode);
- break;
- default:
- printf("Internal confusion!!!\n");
- break;
- }
- }
- else
- {
- /* It's a prototype, so copy each line out */
- if(mode != MakeProtos)
- {
- for(i=0; i<=ndef; i++)
- fprintf(fp_out,"%s\n",funcdef[i]);
- }
- }
- }
- else
- {
- /* It's an extern, so just copy it */
- if(mode != MakeProtos) fprintf(fp_out,"%s\n",buffer);
- }
- }
- else
- {
- /* We're in a #, comment, string, function or blank line.
- Simply copy the line to the output file.
- */
- if(mode != MakeProtos) fprintf(fp_out,"%s\n",buffer);
- }
- }
- }
-
- /*>*************************************************************************
- isInteresting(buffer)
- ---------------------
- Input: char *buffer Line from file
- Returns: int 1: Line is interesting-may be a function
- 0: Line not interesting
-
- Tries to determine whether a line is possibly a function definition.
- Does this by checking, on entry, that we're not a blank line, not in a
- comment, between double or single inverted commas and not already in a
- function definition.
- ***************************************************************************/
- int isInteresting(char *buffer)
- {
- static int comment_count = 0,
- bra_count = 0,
- inSIC = 0,
- inDIC = 0;
-
- int i,
- retval = 0,
- isBlank = TRUE;
-
- /* Not interested if it's a #define, etc. */
- if(buffer[0] == '#') return(0);
-
- /* If all of these are unset when we enter, we're interested */
- if(!bra_count && !inDIC && !inSIC && !comment_count) retval = 1;
-
- /* If the first thing in this string was a comment we're no longer
- interested.
- */
- for(i=0; buffer[i] && (buffer[i] == ' ' || buffer[i] == '\t'); i++);
- if(buffer[i] == '/' && buffer[i+1] == '*') retval = 0;
-
- /* Step along the line */
- for(i=0; i<strlen(buffer); i++)
- {
- /* We're not interested in anything else if this is a
- C++ style comment
- */
- if(buffer[i] == '/' && buffer[i+1] == '/') return(0);
-
- if(buffer[i] != ' ' && buffer[i] != '\t') isBlank = FALSE;
-
- /* See if we're moving into a string */
- if((buffer[i] == DIC) && (comment_count==0) && !inSIC) toggle(inDIC);
- if((buffer[i] == SIC) && (comment_count==0) && !inDIC)
- {
- toggle(inSIC);
- }
-
- /* If we're not in a string */
- if(!inDIC && !inSIC)
- {
- /* See if we're moving into a comment */
- if((buffer[i] == '/') && (buffer[i+1] == '*')) comment_count++;
- /* See if we're moving out of a comment */
- if((buffer[i] == '*') && (buffer[i+1] == '/')) comment_count--;
-
- /* If we're not in a comment we must be in code.
- Update the curly bracket count
- */
- if(!comment_count)
- {
- if(buffer[i] == '{') bra_count++;
- if(buffer[i] == '}') bra_count--;
- }
- }
- }
-
- /* If it's a blank line, we're not interested */
- if(isBlank) retval = 0;
-
- return(retval);
- }
-
-
- /*>*************************************************************************
- Ansify(fp, funcdef, ndef, mode)
- -------------------------------
- Input: FILE *fp File to create
- char funcdef[][] Function definition lines
- int ndef Number of definition lines
- int mode Processing mode-generate ANSI or prototypes
- MakeANSI: Create ANSI
- MakeProtos: Create prototypes
-
- If it's already ANSI, just writes it; otherwise assembles function into
- a single buffer line, writes the function name and calls WriteANSI() to
- write the definition of each variable.
- ***************************************************************************/
- void Ansify(FILE *fp,
- char funcdef[MAXLINES][MAXBUFF],
- int ndef,
- int mode)
- {
- int i,
- j,
- width,
- isANSI = TRUE,
- bufflen = 0,
- first = TRUE;
- char *buffer = NULL,
- *bufptr,
- *funptr,
- temp[MAXBUFF],
- func[MAXBUFF],
- varname[80];
-
- ndef++;
-
- /* If none of the lines contains a ;, it's already ANSI */
- for(i=0; i<ndef; i++)
- {
- if(strchr(funcdef[i], ';') != NULL)
- {
- isANSI = FALSE;
- break;
- }
- }
-
- if(isANSI)
- {
- /* It's already ANSI */
- if(mode == MakeANSI)
- {
- /* We're making ANSI, so just output it */
- for(i=0; i<ndef; i++) fprintf(fp, "%s\n", funcdef[i]);
- }
- else /* mode == makeProtos */
- {
- /* We're making prototypes, just output, but put a ; instead
- of a {
- */
- for(i=0; i<ndef; i++)
- {
- for(j=0; j<strlen(funcdef[i]); j++)
- {
- if(funcdef[i][j] != '{')
- {
- putc(funcdef[i][j], fp);
- }
- else
- {
- putc(';', fp);
- i = ndef;
- break;
- }
- }
- putc('\n', fp);
- }
- }
- }
- else /* It's not ANSI, so we convert it. */
- {
- /* First allocate some memory */
- for(i=0; i<ndef; i++) bufflen += strlen(funcdef[i]);
- bufflen += 2;
- buffer = (char *)malloc(bufflen * sizeof(char));
- buffer[0] = '\0';
-
- /* Now build all the strings into the single buffer */
- for(i=0; i<ndef; i++) strcat(buffer, funcdef[i]);
-
- /* V1.3
- Remove comments
- */
- KillComments(buffer);
-
- /* Copy the function part into func */
- for(i=0; buffer[i] != ')'; i++) func[i] = buffer[i];
- func[i] = ')';
- func[i+1] = '\0';
-
- /* Find the first (, copy up to here and print it */
- for(i=0; func[i] != '('; i++) temp[i] = func[i];
- temp[i] = '(';
- temp[i+1] = '\0';
- width = strlen(temp);
- fprintf(fp,"%s",temp);
-
- /* Set bufptr to point to the buffer excluding the function def */
- bufptr = strchr(buffer, ')') + 1;
-
- /* Set funptr to point to start of parameter list */
- funptr = strchr(func, '(') + 1;
-
- /* Step through the parameter list getting a parameter at a time */
- first = TRUE;
- while(*funptr && *funptr != ')')
- {
- if(!first)
- {
- fprintf(fp,",\n");
- for(i=0;i<width;i++) fprintf(fp," ");
- }
- first = FALSE;
- /* Kill spaces */
- for( ; funptr && (*funptr == ' ' || *funptr == '\t'); funptr++) ;
- /* Get a parameter */
- funptr += GetVarName(funptr, varname) + 1;
- /* Write the ANSI version */
- if(WriteANSI(fp, varname, bufptr)) /* V1.1 */
- {
- /* Returns 1, if there was a problem */
- temp[strlen(temp)-1] = '\0';
- printf(" %s()\n",temp);
- }
- }
-
- if(mode == MakeANSI)
- fprintf(fp,")\n{\n");
- else /* mode == MakeProtos */
- fprintf(fp,");\n");
-
- /* Free memory */
- free(buffer);
- }
- }
-
- /*>*************************************************************************
- WriteANSI(fp, varname, definitions)
- -----------------------------------
- Input: FILE *fp File being written
- char *varname Variable name being processed
- char *definitions Assembled KR definitions.
- Returns: int 0: if all OK; 1: if a problem
-
- Creates an ANSI definition from the KR definition and writes it into the
- parameter list.
- ***************************************************************************/
- int WriteANSI(FILE *fp,
- char *varname,
- char *definitions)
- {
- char *start,
- *stop,
- *ptr,
- buffer[MAXBUFF];
- int i;
-
- /*** Find the variable type ***/
-
- /* Set these to the position of varname in the definitions list */
- start = stop = FindVarName(definitions, varname); /* V1.2 */
-
- if(!start)
- {
- printf("Parameter `%s' was not found in definitions for function:\n",varname);
- return(1);
- }
-
- /* Step start back to the start of the list, or the preceeding ; */
- /***V1.3+
- // while(start > definitions && *start != ';' && *start != '/') start--;
- // if(*start == ';' || *start == '/') start++;
- */
- while(start > definitions && *start != ';') start--;
- if(*start == ';') start++;
-
- /***V1.3- */
-
- /* Kill any leading spaces */
- while(*start && (*start == ' ' || *start == '\t')) start++;
-
- /* If there are any commas between start and stop, move stop
- back to the first comma
- */
- for(ptr=start; ptr<=stop; ptr++)
- {
- if(*ptr == ',')
- {
- stop = ptr;
- break;
- }
- }
-
- /* Step stop on to the first , or ; */
- while(*stop && *stop != ',' && *stop != ';') stop++;
-
- /* Now step back over any spaces */
- stop--;
- while(stop > start && (*stop == ' ' || *stop == '\t')) stop--;
-
- /* Now step back over the first variable name */
- while(stop > start && *stop != ' ' && *stop != '\t') stop--;
-
- /* and over the spaces preceeding it */
- while(stop > start && (*stop == ' ' || *stop == '\t')) stop--;
-
- /* Now copy the string delimited by start and stop */
- for(i=0; i<MAXBUFF && start <= stop; i++, start++)
- buffer[i] = *start;
-
- /* Terminate and print it */
- buffer[i] = '\0';
- fprintf(fp,"%s ",buffer);
-
- /*** Now print the variable name with *'s if appropriate ***/
-
- /* Set this to the position of varname in the definitions list */
- start = FindVarName(definitions, varname); /* V1.2 */
-
- /* Step start back to the first non-space character */
- start--;
- while(start > definitions && (*start == ' ' || *start == '\t')) start--;
-
- while(*(start--) == '*')
- fprintf(fp,"*");
-
- fprintf(fp,"%s",varname);
-
- /*** Finally see if it's a [] array ***/
- /* Set these to the position of varname in the definitions list */
- start = stop = FindVarName(definitions, varname); /* V1.2 */
-
- /* Step stop on to the first , or ; */
- while(*stop && *stop != ',' && *stop != ';') stop++;
-
- /* Now step back over any spaces */
- stop--;
- while(stop > start && (*stop == ' ' || *stop == '\t')) stop--;
-
- /* See if there is a [ between start and stop */
- while(start<stop && *start != '[') start++;
-
- /* If a [ was found copy and print the string */
- if(start < stop)
- {
- for(i=0; i<MAXBUFF && start <= stop; i++, start++)
- buffer[i] = *start;
-
- /* Terminate and print it */
- buffer[i] = '\0';
- fprintf(fp,"%s",buffer);
- }
-
- return(0); /* V1.1, all OK */
- }
-
- /*>*************************************************************************
- FindString(buffer, string)
- --------------------------
- Input: char *buffer Buffer being searched
- char *string String to search for
- Returns: *char Pointer to start of string in buffer
-
- Searches for a string in another string returning a pointer to the start
- of the string.
- ***************************************************************************/
- char *FindString(char *buffer,
- char *string)
- {
- char *ptr;
- int ok = FALSE,
- i;
-
- ptr = buffer;
-
- while(!ok)
- {
- /* Step ptr along buffer till we find first character of string */
- while(*ptr && *ptr != *string) ptr++;
-
- /* Return NULL if we didn't find it */
- if(*ptr == '\0') return((char *)NULL);
-
- /* Now compare the rest of the string */
- ok = TRUE;
- for(i=0; i<strlen(string); i++)
- {
- if(ptr[i] != string[i])
- {
- ok = FALSE;
- break;
- }
- }
- ptr++;
- }
- return(--ptr);
- }
- /*>*************************************************************************
- FindVarName(buffer, string)
- ---------------------------
- Input: char *buffer Buffer being searched
- char *string String to search for
- Returns: *char Pointer to start of string in buffer
-
- Works like FindString(), but imposes the additional condition that the
- string must be preceded by a space or * and must be followed by one of
- space ; [ ) or ,
-
- Added for V1.2
- ***************************************************************************/
- char *FindVarName(char *buffer,
- char *string)
- {
- char *ptr;
- int ok = FALSE,
- i;
-
- ptr = buffer;
-
- while(!ok)
- {
- /* Step ptr along buffer till we find first character of string with
- a space or * before it.
- */
- ptr--;
- do
- {
- ptr++;
- while(*ptr && *ptr != *string) ptr++;
- } while(*ptr && *(ptr-1) != ' ' && *(ptr-1) != '*' && *(ptr-1) != ',');
-
- /* Return NULL if we didn't find it */
- if(*ptr == '\0') return((char *)NULL);
-
- /* Now compare the rest of the string */
- ok = TRUE;
- for(i=0; i<strlen(string); i++)
- {
- if(ptr[i] != string[i])
- {
- ok = FALSE;
- break;
- }
- }
-
- /* Check the character after the string */
- if(*(ptr+i) != ';' && *(ptr+i) != '[' &&
- *(ptr+i) != ' ' && *(ptr+i) != ')' && *(ptr+i) != ',') ok = FALSE;
-
- ptr++;
- }
- return(--ptr);
- }
- /*>*************************************************************************
- isFunc(funcdef, ndef)
- ---------------------
- Input: char funcdef[][] Array of lines forming function definition
- int ndef Number of lines
- Returns: int 1: This is a function
- 0: Not a function
-
- Determines whether a possible function definition identified by
- isInteresting() really is a function.
- ***************************************************************************/
- int isFunc(char funcdef[MAXLINES][MAXBUFF],
- int ndef)
- {
- char *termchar;
- int line,
- retval;
-
- /* If it's a prototype, it will not be terminated by a { */
- if(strchr(funcdef[ndef],'{') != NULL) return(1);
-
- /* It's now either a prototype or a K&R function defintion.
- To be a prototype, the first non-space character before the
- ; must be a )
-
- Step backwards.
- */
- line = ndef;
- for(;;)
- {
- termchar = strchr(funcdef[line],';') - 1;
- while(termchar >= funcdef[line] &&
- (*termchar == ' ' || *termchar == '\t'))
- termchar--;
-
- /* If we stepped back beyond the start of the line, go to the
- previous line
- */
- if(termchar < funcdef[line])
- {
- line--;
- if(line < 0) break;
- termchar = funcdef[line] + strlen(funcdef[line]);
- }
- else
- {
- break;
- }
- }
-
- /* OK, see if the character was a ) */
- if(*termchar == ')')
- retval = 0;
- else
- retval = 1;
-
- return(retval);
- }
-
- /*>***********************************************************************
- terminate(string)
- -----------------
- I/O: char *string A character string
- Returns: void
-
- Terminates a string at the first \n
- *************************************************************************/
- void terminate(char *string)
- {
- int i;
-
- for(i=0;string[i];i++)
- {
- if(string[i] == '\n')
- {
- string[i] = '\0';
- break;
- }
- }
- }
- /*>***********************************************************************
- DeAnsify(fp, funcdef, ndef)
- ---------------------------
- Input: FILE *fp File being written
- char funcdef[][] Function definition array
- int ndef Number of definition lines
- Returns: void
-
- Writes a K&R function definition from the ANSI (or K&R) form in funcdef.
- If it's already K&R, just writes it; otherwise assembles function into
- a single buffer line, writes the function name and calls WriteKR() to
- write the definition of each variable.
- *************************************************************************/
- void DeAnsify(FILE *fp,
- char funcdef[MAXLINES][MAXBUFF],
- int ndef)
- {
- int i,
- j,
- nparam,
- isKR = FALSE,
- bufflen = 0,
- last = FALSE;
- char *buffer = NULL,
- *bufptr,
- *funptr,
- *ptr,
- *start,
- *stop,
- temp[MAXBUFF],
- func[MAXBUFF],
- varname[80];
-
- ndef++;
-
- /* If any of the lines contains a ;, it's already KR */
- for(i=0; i<ndef; i++)
- {
- if(strchr(funcdef[i], ';') != NULL)
- {
- isKR = TRUE;
- break;
- }
- }
-
- if(isKR)
- {
- /* It's already KR, so just output it */
- for(i=0; i<ndef; i++) fprintf(fp, "%s\n", funcdef[i]);
- }
- else /* It's not KR, so we convert it. */
- {
- /* First allocate some memory */
- for(i=0; i<ndef; i++) bufflen += strlen(funcdef[i]);
- bufflen += 2;
- buffer = (char *)malloc(bufflen * sizeof(char));
- buffer[0] = '\0';
-
- /* Now build all the strings into the single buffer ignoring comments */
- for(i=0; i<ndef; i++) strcat(buffer,funcdef[i]);
-
- /* Find the first (, copy up to here and print it */
- for(i=0; buffer[i] != '('; i++) temp[i] = buffer[i];
- temp[i] = '(';
- temp[i+1] = '\0';
- fprintf(fp,"%s",temp);
-
- /* Set bufptr to point to the buffer excluding the function name */
- bufptr = strchr(buffer, '(') + 1;
-
- /* Count the number of commas in the parameter list */
- nparam = 0;
- for(funptr = bufptr; *funptr && *funptr != ')'; funptr++)
- if(*funptr == ',') nparam++;
-
- if(nparam)
- {
- /* If there were *any* commas, the number of parameters is one
- more than the number of commas
- */
- nparam++;
- }
- else
- {
- /* If there weren't any commas, there are either 0 or 1 params.
- If there's only white space, or `void' between the ( and )
- there are 0 parameters. Otherwise, there's 1
- */
- if(FindString(bufptr,"void") || FindString(bufptr,"VOID"))
- {
- nparam = 0;
- }
- else
- {
- for(funptr = bufptr; *funptr && *funptr != ')'; funptr++)
- {
- if(*funptr != ' ' && *funptr != '\t')
- {
- nparam = 1;
- break;
- }
- }
- }
- }
-
- /* If there weren't any parameters we can just output a closing
- parenthesis an opening { and return.
- */
- if(nparam==0)
- {
- fprintf(fp,")\n{\n");
- free(buffer);
- return;
- }
-
- /* Step through the parameter list getting a parameter at a time.
- Assemble these into func.
- The variable names are delimited by a , a [ or the closing )
- */
- func[0] = '\0';
- funptr = bufptr;
- for(i=0; i<nparam; i++)
- {
- /* Step funptr on to the next , or ) */
- if((funptr = strchr(funptr,',')) == NULL)
- {
- funptr = strchr(bufptr,')');
- last = TRUE;
- }
-
- /* Step back over any spaces */
- stop = funptr-1;
- while(stop>bufptr && (*stop==' ' || *stop=='\t')) stop--;
-
- /* Step back to the start of the variable name */
- start = stop;
- while(start>=bufptr && *start!=' ' && *start!='\t' && *start != '*')
- start--;
- start++;
-
- /* Copy the variable name into our function buffer adding
- a , and space or ) as appropriate.
- */
- for(j=0; start<=stop; start++, j++)
- temp[j] = *start;
- temp[j] = '\0';
-
- if((ptr = strchr(temp,'[')) != NULL)
- *ptr = '\0';
-
- if(last)
- strcat(temp,")");
- else
- strcat(temp,", ");
-
- strcat(func, temp);
- funptr++;
- }
-
- /* We can now echo the parameter list to the output file */
- fprintf(fp,"%s\n",func);
-
- /* Work through the parameter list writing the parameter
- definition lines
- */
- funptr = func;
- while(*funptr && *funptr != ')')
- {
- /* Kill spaces */
- for( ; funptr && (*funptr == ' ' || *funptr == '\t'); funptr++) ;
- /* Get a parameter */
- funptr += GetVarName(funptr, varname) + 1;
- /* Write the K&R version */
- WriteKR(fp, varname, bufptr);
- }
-
- fprintf(fp,"{\n");
-
- /* Free memory */
- free(buffer);
- }
- }
-
- /*>*************************************************************************
- WriteKR(fp, varname, definitions)
- ---------------------------------
- Input: FILE *fp File being written
- char *varname Variable being processed
- char *definitions ANSI style definitions
- Returns: void
-
- Writes a variable definition in K&R form by extracting information from
- the ANSI definition.
- ***************************************************************************/
- void WriteKR(FILE *fp,
- char *varname,
- char *definitions)
- {
- char *start,
- *stop,
- temp[MAXBUFF];
- int i;
-
- /* Find the variable name in the definitions */
- /*** V1.5+
- // start = stop = FindString(definitions,varname);
- */
- start = stop = FindVarName(definitions,varname);
- /*** V1.5- */
-
- /* Step start back to the preceeding , / or (, then forward
- over any spaces
- */
- while(start >= definitions && *start != '(' &&
- *start != ',' && *start != '/')
- start--;
- start++;
- while(start<stop && (*start==' ' || *start=='\t')) start++;
-
- /* Step stop on to the following , or ) */
- while(*stop && *stop != ')' && *stop != ',') stop++;
- stop--;
-
- /* Copy the variable definition, add a ; and output. */
- for(i=0; start<=stop; start++, i++)
- temp[i] = *start;
- temp[i] = ';';
- temp[i+1] = '\0';
-
- fprintf(fp,"%s\n",temp);
- }
-
- /*>*************************************************************************
- KillComments(buffer)
- --------------------
- I/O: char *buffer String from which to remove any comments
- Returns: void
-
- Takes a string and removes any section enclosed in comments.
-
- Added for V1.3
- ***************************************************************************/
- void KillComments(char *buffer)
- {
- int in = 0,
- out = 0,
- comment = 0,
- len;
-
- len = strlen(buffer);
-
- for(in=0;in<len;in++)
- {
- if(buffer[in] == '/' && buffer[in+1] == '*') comment++;
- if(buffer[in-2] == '*' && buffer[in-1] == '/') comment--;
-
- if(!comment) buffer[out++] = buffer[in];
- }
-
- buffer[out] = '\0';
- }
-
-