G
G Patel
I wrote the following program to remove C89 type comments from stdin
and send it to stdout (as per exercise in K&R2) and it works but I was
hoping more experienced programmer would critique the layout/style/etc.
[I accidentally posted this before in comp.std.c, not trying to post to
several groups on purpose]
Any comments will be helpful. Thank you.
/*
****************************************************
C89/90 COMMENT REMOVER
======================
Description: This program removes all C89/90 style
commnets from a c source (file).
The program does not support C++/C99
style comments.
Input/Ouput: Input for the c source is taken from
stdin and output is to stdout.
Command-line piping of c source files
is expected.
Author: Gaya Patel
Date: Feb 24, 2005
****************************************************
*/
#include <stdio.h>
#define OUT 0
#define IN 1
int main()
{
int c; /* input character for state machine cycle */
/* state variables */
int comstate = OUT; /* state variable C, in explanation below */
int entry = OUT; /* state variable E, in explanation below */
int quostate = OUT; /* state variable Q, in explanation below */
/* --------------- */
/*************************************************************
OVERVIEW OF STATE MACHINE DESIGN:
*********************************
State machine input: c = getchar()
State machine cycle: on every c = getchar() input
State A: (C:E:Q) = (OUT: OUT: OUT) = (0: 0: 0)
-----------------------------------------------------
If input is " transition to STATE Q
If input is / transition to STATE B
Otherwise no transition
State B: (C:E:Q) = (OUT: IN: OUT) = (0: 1: 0)
-----------------------------------------------------
If input is * transition to STATE C
If input is " transition to STATE Q and putchar('/')
Otherwise transition to STATE A and putchar('/')
State C: (C:E:Q) = (IN: OUT: OUT) = (1: 0: 0)
------------------------------------------------------
If input is * transition to STATE D
Otherwise no transition
State D: (C:E:Q) = (IN: IN: OUT) = (1: 1: 0)
------------------------------------------------------
If input is / transition to STATE D
Otherwise transition to STATE C
State E (C:E:Q) = (IN: IN: IN) = (1: 1: 1)
------------------------------------------------------
Any input transition to A
STATE Q: (C:E:Q) = (OUT: OUT: IN) = (0: 0: 1)
------------------------------------------------------
If input is " transition to STATE A
Otherwise no transition
OUTPUT FORMING LOGIC SPECIAL CASE FOR STATE B
**********************************************
The output forming logic of the state machine checks the
post-transition state variables to decide whether or not
to output the input char, or to discard it (not output).
In the case of post-transition STATE B, at that point, it
is still not sure whether the '/' is the start of a
comment or not. The output forming logic simply discards
this character (assumes start of comment). Therefore,
within the state machine design, an extra '/' is outputted
upon any transition from B other than B->C.
******************************************************************/
while((c = getchar()) != EOF)
{
/* ***** state transition logic ***** */
if(comstate == OUT && entry == OUT && quostate == OUT)
{ /* IF IN STATE A */
if(c == '"')
{
quostate = IN; /* TRANSITION TO STATE Q */
}
else if(c == '/')
{
entry = IN; /* TRANSITION TO STATE B */
}
else
{
/* STAY IN STATE A */
}
}
else if(comstate == OUT && entry == IN && quostate == OUT)
{ /* IF IN STATE B */
if(c == '*')
{
comstate = IN; /* TRANSITION TO STATE C */
entry = OUT;
}
else if('"')
{
quostate = IN; /* TRANSITION TO STATE Q */
entry = OUT;
putchar('/'); /* Print '/' */
}
else
{
entry = OUT; /* TRANSITION TO STATE A */
putchar('/'); /* Print '/' */
}
}
else if(comstate == IN && entry == OUT && quostate == OUT)
{ /* IF IN STATE C */
if(c == '*')
{
entry = IN; /* TRANSITION TO STATE D */
}
else
{
/* STAY IN C */
}
}
else if(comstate == IN && entry == IN && quostate == OUT)
{ /* IF IN STATE D */
if(c == '/')
{
quostate = IN; /* TRANSITION TO STATE E */
}
else
{
entry = OUT; /* TRANSITION TO STATE C */
}
}
else if(comstate == IN && entry == IN && quostate == IN)
{ /* IF IN STATE E */
comstate = OUT;
entry = OUT; /* TRANSITION TO STATE A */
quostate = OUT;
}
else if(quostate == IN) /* IF IN STATE Q */
{
if(c == '"')
{
quostate = OUT; /* TRANSITION TO STATE A */
}
else
{
/* STAY IN STATE Q */
}
}
else
{
/* INVALID STATE */
}
/**********************************************************
OUTPUT FORMING LOGIC
********************
* The output forming logic is simply an if statement
that checks the post-transition state.
* If the state is A or Q, the output is allowed,
otherwise no output occur on that cycle
* See state B's special case in the description of
the state machine (top of module).
*********************************************************/
/* ***** output forming logic ***** */
if(c == '\n')
{
putchar('\n');
}
else if(comstate == OUT && entry == OUT)
{
putchar(c);
}
} /* end of large while loop */
return 0;
}
/**/
and send it to stdout (as per exercise in K&R2) and it works but I was
hoping more experienced programmer would critique the layout/style/etc.
[I accidentally posted this before in comp.std.c, not trying to post to
several groups on purpose]
Any comments will be helpful. Thank you.
/*
****************************************************
C89/90 COMMENT REMOVER
======================
Description: This program removes all C89/90 style
commnets from a c source (file).
The program does not support C++/C99
style comments.
Input/Ouput: Input for the c source is taken from
stdin and output is to stdout.
Command-line piping of c source files
is expected.
Author: Gaya Patel
Date: Feb 24, 2005
****************************************************
*/
#include <stdio.h>
#define OUT 0
#define IN 1
int main()
{
int c; /* input character for state machine cycle */
/* state variables */
int comstate = OUT; /* state variable C, in explanation below */
int entry = OUT; /* state variable E, in explanation below */
int quostate = OUT; /* state variable Q, in explanation below */
/* --------------- */
/*************************************************************
OVERVIEW OF STATE MACHINE DESIGN:
*********************************
State machine input: c = getchar()
State machine cycle: on every c = getchar() input
State A: (C:E:Q) = (OUT: OUT: OUT) = (0: 0: 0)
-----------------------------------------------------
If input is " transition to STATE Q
If input is / transition to STATE B
Otherwise no transition
State B: (C:E:Q) = (OUT: IN: OUT) = (0: 1: 0)
-----------------------------------------------------
If input is * transition to STATE C
If input is " transition to STATE Q and putchar('/')
Otherwise transition to STATE A and putchar('/')
State C: (C:E:Q) = (IN: OUT: OUT) = (1: 0: 0)
------------------------------------------------------
If input is * transition to STATE D
Otherwise no transition
State D: (C:E:Q) = (IN: IN: OUT) = (1: 1: 0)
------------------------------------------------------
If input is / transition to STATE D
Otherwise transition to STATE C
State E (C:E:Q) = (IN: IN: IN) = (1: 1: 1)
------------------------------------------------------
Any input transition to A
STATE Q: (C:E:Q) = (OUT: OUT: IN) = (0: 0: 1)
------------------------------------------------------
If input is " transition to STATE A
Otherwise no transition
OUTPUT FORMING LOGIC SPECIAL CASE FOR STATE B
**********************************************
The output forming logic of the state machine checks the
post-transition state variables to decide whether or not
to output the input char, or to discard it (not output).
In the case of post-transition STATE B, at that point, it
is still not sure whether the '/' is the start of a
comment or not. The output forming logic simply discards
this character (assumes start of comment). Therefore,
within the state machine design, an extra '/' is outputted
upon any transition from B other than B->C.
******************************************************************/
while((c = getchar()) != EOF)
{
/* ***** state transition logic ***** */
if(comstate == OUT && entry == OUT && quostate == OUT)
{ /* IF IN STATE A */
if(c == '"')
{
quostate = IN; /* TRANSITION TO STATE Q */
}
else if(c == '/')
{
entry = IN; /* TRANSITION TO STATE B */
}
else
{
/* STAY IN STATE A */
}
}
else if(comstate == OUT && entry == IN && quostate == OUT)
{ /* IF IN STATE B */
if(c == '*')
{
comstate = IN; /* TRANSITION TO STATE C */
entry = OUT;
}
else if('"')
{
quostate = IN; /* TRANSITION TO STATE Q */
entry = OUT;
putchar('/'); /* Print '/' */
}
else
{
entry = OUT; /* TRANSITION TO STATE A */
putchar('/'); /* Print '/' */
}
}
else if(comstate == IN && entry == OUT && quostate == OUT)
{ /* IF IN STATE C */
if(c == '*')
{
entry = IN; /* TRANSITION TO STATE D */
}
else
{
/* STAY IN C */
}
}
else if(comstate == IN && entry == IN && quostate == OUT)
{ /* IF IN STATE D */
if(c == '/')
{
quostate = IN; /* TRANSITION TO STATE E */
}
else
{
entry = OUT; /* TRANSITION TO STATE C */
}
}
else if(comstate == IN && entry == IN && quostate == IN)
{ /* IF IN STATE E */
comstate = OUT;
entry = OUT; /* TRANSITION TO STATE A */
quostate = OUT;
}
else if(quostate == IN) /* IF IN STATE Q */
{
if(c == '"')
{
quostate = OUT; /* TRANSITION TO STATE A */
}
else
{
/* STAY IN STATE Q */
}
}
else
{
/* INVALID STATE */
}
/**********************************************************
OUTPUT FORMING LOGIC
********************
* The output forming logic is simply an if statement
that checks the post-transition state.
* If the state is A or Q, the output is allowed,
otherwise no output occur on that cycle
* See state B's special case in the description of
the state machine (top of module).
*********************************************************/
/* ***** output forming logic ***** */
if(c == '\n')
{
putchar('\n');
}
else if(comstate == OUT && entry == OUT)
{
putchar(c);
}
} /* end of large while loop */
return 0;
}
/**/