/** ************************************************************************ * program to identify and print all C/C++ based comments within a program * * all other elements of a C/C++ progrm are ignored * * * * processing is based on a DFA, shown in diagram dfa-comments.png * * * ***************************************************************************/ #include #include // for malloc, free #include // for character type functions /** ******************************************************************************* * enumerated type of character categories * *********************************************************************************/ typedef enum { Slash, Star, NewLine, /* Digit, Alpha, Period, Digit, Alpha, Space, */ Other, EndFile, NumTypes } charType; /** ******************************************************************************* * structures to store data for each state transition. * *********************************************************************************/ typedef struct { char * str; /* pointer to array of characters (stored) */ int numAllocated; /* number of array elemens allocated */ int numUsed; /* number of array elements used */ } stringData; #define initStringSize 10; typedef int (* transitionFunc) (char, stringData *); /** ******************************************************************************* * function to add character to stringData * *********************************************************************************/ void addChar (char ch, stringData * data) { // check if more space needed in array if (data->numUsed == data->numAllocated) { //create larger array char * tempData = malloc (2 * data->numAllocated * sizeof(char)); //copy old array to larger new one for (int i = 0; i < data->numAllocated; i++) tempData[i] = data->str[i]; data->numAllocated *= 2; free (data->str); data->str = tempData; } data->str[data->numUsed] = ch; data->numUsed++; } /** ******************************************************************************* * transition functions * *********************************************************************************/ /******************************************************************************** no processing needed input igored return to starting state */ int noproc (char inputCh, stringData * data) { /* if (inputCh == EOF) printf ("noproc: inputCh: EOF\n"); else printf ("noproc: inputch: %c", inputCh); */ if (data->str != NULL) { free (data->str); data->str = NULL; data->numUsed = data->numAllocated = 0; } return 0; // move to starting state } /******************************************************************************** prepare to check for start of comment input igored return to state checking second character at start of comment */ int chkcmt (char inputCh, stringData * data) { if (data->str != NULL) { free (data->str); data->numUsed = data->numAllocated = 0; } return 3; // move to start-of-comment state } /******************************************************************************** no start of comment after '/' read input igored return to starting state */ int nocmt (char inputCh, stringData * data) { if (data->str != NULL) { free (data->str); data->numUsed = data->numAllocated = 0; } return 0; // move to start-of-comment state } /* * * * * * * * * * * * * comment type 1 processing * * * * * * * * * * * * * */ /******************************************************************************** set up processing for comment, type 1 comment starts with // (already checked) and ontinues until \n or EOF new data parameter created and initialzed return to state checking second character at start of comment */ int strtcmt1 (char inputCh, stringData * data) { if (data->str != NULL) { free (data->str); } data->numAllocated = initStringSize;; data->str = malloc (data->numAllocated *sizeof (char)); data->numUsed = 0; return 4; // move to start-of-comment state } /******************************************************************************** continue processing within comment, type 1 add character to data parameter continue in state 4 */ int cmt1cont (char inputCh, stringData * data) { addChar (inputCh, data); return 4; } /******************************************************************************** conclude processing of comment, type 1 comment ends \n or EOF print comment return to start state */ int cmt1done (char inputCh, stringData * data) { // null character goes at end of string addChar (0, data); // print comment with heading printf ("Comment: Type 1 (//):\n "); printf ("%s\n", data->str); return 0; } /* * * * * * * * * * * * * comment type 2 processing * * * * * * * * * * * * * */ /******************************************************************************** set up processing for comment, type 2 comment starts with // (already checked) and ontinues until \n or EOF new data parameter created and initialzed return to state checking second character at start of comment */ int strtcmt2 (char inputCh, stringData * data) { if (data->str != NULL) { free (data->str); } data->numAllocated = initStringSize;; data->str = malloc (data->numAllocated *sizeof (char)); data->numUsed = 0; return 1; // move to start-of-comment state } /******************************************************************************** continue processing within comment, type 2 add character to data parameter indent after a newline \n for output formatting continue in state 1 */ int cmt2cont (char inputCh, stringData * data) { addChar (inputCh, data); // if comment contains \n character, indent next line five spaces if (inputCh == '\n') { addChar(' ', data); addChar(' ', data); addChar(' ', data); addChar(' ', data); addChar(' ', data); } return 1; } /******************************************************************************** proces '*' within comment, type 2 * encountered within comment need to read next character to determine if comment is ending state 2 remembers * encounted in input */ int cmt2star(char inputCh, stringData * data) { return 2; } /******************************************************************************** no '*' after '*' within comment, type 2 add * and next input character to comment return back to regular ccomment type 2 processing */ int cmt2withStar(char inputCh, stringData * data) { addChar ('*', data); addChar (inputCh, data); return 1; } /******************************************************************************** proces '*' within comment, type 2 comment ends \n or EOF print comment return to start state */ int cmt2done (char inputCh, stringData * data) { // null character goes at end of string addChar (0, data); // print comment with heading printf ("Comment: Type 2 (/* */):\n "); printf ("%s\n", data->str); return 0; } /******************************************************************************** premature EOF in comment type 2 return to start state */ int error (char inputCh, stringData * data) { printf ("Error in program: premature end of file encountered\n"); printf ("processing terminated\n"); exit (1); } int main ( ) { printf ("Program to print all comments with a C/C++ program\n"); // DFA Table for 6 states, NumTypes input character types transitionFunc table [6 ][NumTypes] = { // Slash , Star , NewLine , Other , EndFile state { chkcmt , noproc , noproc , noproc , noproc }, // 0 { cmt2cont , cmt2star , cmt2cont , cmt2cont , error }, // 1 { cmt2done , cmt2withStar, cmt2withStar, cmt2withStar, error }, // 2 { strtcmt1 , strtcmt2 , nocmt , nocmt , nocmt }, // 3 { cmt2cont , cmt2cont , cmt1done , cmt1cont , cmt1done }, // 4 { error , error , error , error ,error } // 5 }; stringData paramData = {NULL, 0, 0}; int currentState = 0; printf ("Enter C-program code or use input redirction with file\n"); char inputCh; inputCh = getchar (); while ((currentState != 0) || (inputCh != EOF)) { //printf ("current state: %d\n", currentState); /* determine input category */ charType inputType; if (inputCh == '/') inputType = Slash; else if (inputCh == '*') inputType = Star; else if (inputCh == '\n') inputType = NewLine; /* else if (isdigit(inputCh)) inputType = Digit; else if (isalpha (inputCh)) inputType = Alpha; else if (inputCh == '.') inputType = Period; else if (inputCh == ' ') inputType = Space; */ else if (inputCh == EOF) inputType = EndFile; else inputType = Other; currentState = table[currentState][inputType] (inputCh, ¶mData); // prepare to process next character inputCh = getchar (); } printf ("\nprogram processed\n"); printf ("processing terminated\n"); return 0; }