/*
** makefun.c - C Declaration Extraction Program
** Written October, 1995 and placed in the
** public domain by Ted Merrill.
**
** The purpose of this program is to
** automatically create a header file containing
** declarations extracted from function and/or
** data definitions or declarationsin a C or
** C++ source file. Preparation of the source
** file is required as follows:
**
** To prepare the source file for extraction,
** you must prefix definitions and declarations
** to be extracted with special comments that
** begin at column 1. Please see example at
** bottom of this file. If the item to be
** extracted must begin with "extern", you must
** place the word "extern" before the special
** comment, since the extractor will prepend an
** "extern" on its own. To "comment out" the
** special comments, move them right from
** column 1.
**
** Compilation: nothing special.
**
** Execution:
** Redirect stdin to the source file and stdout
** to the output file. For example, try:
**
** makefun <makefun.c >makefun.out
**
** and:
**
** makefun <makefun.out >makefun1.out
**
** Using the results of execution:
** The output file should be #included into
** those C/C++ files using the functions whose
** declarations were extracted.
*/
#include <stdio.h>
enum makefun_state
{
STATE_NEW_LINE, /* at beginning of line,
outside of declaration */
STATE_SILENT_LINE, /* inside of a line
outside a declaration */
STATE_MATCH, /* inside a potential beginning of a
declaration */
STATE_IN_C, /* inside a C comment in a declaration */
STATE_C_END, /* at possible end of C comment */
STATE_IN_CPP, /* inside a C++ comment in a declaration */
STATE_IN_DECL, /* inside a declaration, but not in a comment */
STATE_C_BEGIN, /* possible beginning of C comment in a
declaration */
};
#define CMATCH "/*-E-" /* C-style special comment beginning*/
#define CPPMATCH "//-E-" /* C++-style special comment beginning*/
int main()
{
/* begin at new line */
enum makefun_state state = STATE_NEW_LINE;
int imatch; /* index into matching string */
int bmatchc; /* true if we match C comment so far */
int bmatchcpp; /* true if we match C++ comment so far */
int ch; /* character from stdin */
printf("\n/*This is automatically generated,");
printf(" not a source file! */\n");
while ( (ch = getchar()) != EOF )
{ /* loop until end of file; all input at top only! */
switch( state )
{
case STATE_NEW_LINE: /* here at begin of line,
outside decl. */
if ( ch == CMATCH[0] )
{
state = STATE_MATCH;
bmatchc = 1; /* match C comment so far */
imatch = 1; /* match index 1 next time */
}
else bmatchc = 0;
if ( ch == CPPMATCH[0] )
{
state = STATE_MATCH;
bmatchcpp = 1; /* match C++ comment so far */
imatch = 1; /* match index 1 next time */
}
else bmatchcpp = 0;
if ( bmatchc || bmatchcpp ) ;
else if ( ch == '\n' ) ;
else state = STATE_SILENT_LINE;
break;
case STATE_SILENT_LINE: /* here inside a line,
outside of decl. */
if ( ch == '\n' ) state = STATE_NEW_LINE;
break;
case STATE_MATCH: /* here at begin of potential
declaration */
if ( bmatchc && ch != CMATCH[imatch] )
bmatchc = 0;
if ( bmatchcpp && ch != CPPMATCH[imatch] )
bmatchcpp = 0;
imatch++;
if ( bmatchc && ! CMATCH[imatch] )
{ /* found a C special comment match */
state = STATE_IN_C;
printf("\n\nextern\n"); /* make declaration
extern! */
printf("%s", CMATCH ); /* start emitting! */
}
else if ( bmatchcpp && ! CPPMATCH[imatch] )
{ /* found a C++ special comment match */
state = STATE_IN_CPP;
printf("\n\nextern\n"); /* make declaration
extern! */
printf("%s", CPPMATCH ); /* start emitting! */
}
if ( bmatchc || bmatchcpp ) ;
else if ( ch == '\n' ) state = STATE_NEW_LINE;
else state = STATE_SILENT_LINE;
break;
case STATE_IN_C: /* here inside C comment in a
declaration */
putchar( ch );
if ( ch == '*' ) state = STATE_C_END;
break;
case STATE_C_END: /* at possible end of C style
comment */
putchar( ch );
if ( ch == '/' ) state = STATE_IN_DECL;
else if ( ch == '*' ) ;
else state = STATE_IN_C;
break;
case STATE_IN_CPP: /* here inside C++ comment in a
declaration */
putchar( ch );
if ( ch == '\n' ) state = STATE_IN_DECL;
break;
case STATE_IN_DECL: /* here inside decl. but not
inside comment */
if ( ch == '/' ) state = STATE_C_BEGIN;
else if ( ch == '{' || ch == '=' || ch == ';' )
{
ch = ';'; /* replace with terminator
semicolon */
state = STATE_SILENT_LINE;
}
putchar(ch);
break;
case STATE_C_BEGIN: /* possible begin of comment in
declaration */
if ( ch == '*' ) state = STATE_IN_C;
else if ( ch == '/' ) state = STATE_IN_CPP;
else if ( ch == '{' || ch == '=' || ch == ';' )
{
ch = ';'; /* replace with terminator
semicolon */
state = STATE_SILENT_LINE;
}
else state = STATE_IN_DECL;
putchar(ch);
break;
}
}
printf("\n\n/*-------- end ----------*/\n");
return 0;
}
/* End of File */