/************************************************************************** * * Copyright (c) 1996, 1997 Stephen Karg * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Description: Reads in a C program file and counts the number of * logical lines of code. Also displays each function * and displays the number of logical lines of code * for that function. * * History: 1: 05-Dec-1996: Copied loc.c to create file - Steve Karg * 2: 09-Jan-1997: Corrected flaw. The single quote when used * with control codes would skip if the control * code was a \'. - Steve Karg * 3: 16-Jan-1997: Added code to check for old style of function * declarations. Added some additional keywords * for the symbols that aren't counted. This will * help avoid false starts for function detection * and counting. - Steve Karg * 4: 03-Feb-1997: Added code to the function check routing to * allow counting of the function line and the * last brace. This will enable better counts * for estimate purposes. - Steve Karg * 5: 18-Feb-1997: Added code that counts the number of comment * lines of code, and determines the comment * density. Added code that uses the filename * as entered from the command line and removes * any extraneous logicals or directory paths * for the help screen (Usage function) - Steve Karg * 6: 26-Aug-1997: Modified the # precompiler to allow for non-first * column entry. Modified the code for the MS-DOS * operating system. Added checking for C++ comment * style. - Steve Karg * 7: 23-Oct-1997: Added C++ keywords. Changed the constant size * of the keyword array to a variable size. Found * out in the process that sizeof() returns the * memory size of the array, not the array size. * - Steve Karg * **************************************************************************/ static char version_date[] = {"23-Oct-1997"}; static char version_number[] = {"1.7"}; #include #include #include #include #include #include #include /* LOCAL CONTSTANTS */ #define MAX_LINE_SIZE (80) #define MAX_FUNCTION_NAME (32) #define TRUE (1) #define FALSE (0) /* set up counter type */ typedef unsigned long int COUNTER; /* structure for keyword list */ typedef struct keyword { char data[MAX_LINE_SIZE]; /* string containing the key word */ unsigned char valid_flag; /* is this used for LOC count? */ } KEYWORD; /* array for keywords */ static KEYWORD c_keywords[] = { /* ANSI C LOC countable reserved words and symbols (15) */ {"case", TRUE}, {"default", TRUE}, {"do", TRUE}, {"else", TRUE}, {"enum", TRUE}, {"for", TRUE}, {"if", TRUE}, {"struct", TRUE}, {"switch", TRUE}, {"union", TRUE}, {"while", TRUE}, {"#", TRUE}, {";", TRUE}, {",", TRUE}, {"}", TRUE}, /* ANSI C++ LOC reserved words (26) */ {"bool", FALSE}, {"catch", TRUE}, {"class", TRUE}, {"const_cast",FALSE}, {"delete", FALSE}, {"dynamic_cast",FALSE}, {"false", FALSE}, {"friend", TRUE}, {"inline", TRUE}, {"mutable", FALSE}, {"namespace",FALSE},{"new", FALSE}, {"operator", TRUE}, {"private", TRUE}, {"protected",TRUE}, {"public", TRUE}, {"reinterpret_cast",FALSE},{"static_cast",FALSE}, {"template", TRUE}, {"this", FALSE}, {"throw", FALSE}, {"true", FALSE}, {"try", TRUE}, {"typeid", FALSE}, {"using", FALSE}, {"virtual", TRUE}, /* ANSI C Reserved words that are not LOC countable (28) */ {"asm", FALSE}, {"auto", FALSE}, {"break", FALSE}, {"char", FALSE}, {"const", FALSE}, {"continue", FALSE}, {"do", FALSE}, {"double", FALSE}, {"entry", FALSE}, {"enum", FALSE}, {"extern", FALSE}, {"float", FALSE}, {"fortran", FALSE}, {"goto", FALSE}, {"int", FALSE}, {"long", FALSE}, {"register", FALSE}, {"return", FALSE}, {"short", FALSE}, {"signed", FALSE}, {"sizeof", FALSE}, {"static", FALSE}, {"unsigned", FALSE}, {"void", FALSE}, {"volatile", FALSE}, /* ANSI C symbols that are not countable (25) */ {"!", FALSE}, {"%", FALSE}, {"^", FALSE}, {"&", FALSE}, {"*", FALSE}, {"(", FALSE}, {")", FALSE}, {"-", FALSE}, {"_", FALSE}, {"+", FALSE}, {"=", FALSE}, {"~", FALSE}, {"[", FALSE}, {"]", FALSE}, {"\\", FALSE}, {"|", FALSE}, {":", FALSE}, {"'", FALSE}, {"\"", FALSE}, {"{", FALSE}, {".", FALSE}, {"<", FALSE}, {">", FALSE}, {"/", FALSE}, {"?", FALSE}, /* ANSI C compound symbols that are not countable (21) */ /* NOTE: the program as currently written does not recognize compound symbols */ {"+=", FALSE}, {"-=", FALSE}, {"*=", FALSE}, {"/=", FALSE}, {"%=", FALSE}, {"<<=", FALSE}, {">>=", FALSE}, {"&=", FALSE}, {"^=", FALSE}, {"|=", FALSE}, {"->", FALSE}, {"++", FALSE}, {"--", FALSE}, {"<<", FALSE}, {"<<", FALSE}, {"<=", FALSE}, {">=", FALSE}, {"==", FALSE}, {"!=", FALSE}, {"&&", FALSE}, {"||", FALSE} }; /* Rather than use a constant (#define), this is easier to maintain */ static size_t Max_Keywords = sizeof(c_keywords)/sizeof(KEYWORD); /* This element will hold function names and size of function */ typedef struct function { char name[MAX_FUNCTION_NAME]; /* function name */ COUNTER loc_count; /* number of logical lines of code */ struct function *next; /* next element in list - NULL if none */ } FUNCTION; /* set up generic element */ typedef struct function ELEMENT; /* set up the start of the linked list */ static ELEMENT *head; /* set up debug */ static unsigned char Debug_Flag; static FILE *debug_file_ptr; static char debug_string[256]; static char Append_File_Name[256]; static char C_Filename[256]; /* FUNCTION PROTOTYPES */ ELEMENT *create_list_element(void); void add_element(ELEMENT *e); void delete_elements(void); ELEMENT *last_element(void); FILE *open_input_file(char *filename); FILE *open_debug_file(void); char *debug_file_date(void); void Interpret_Arguments(int argc, char *argv[]); void Usage(char *filename); void print_functions(char *filename,COUNTER loc,COUNTER ploc,COUNTER cloc); void check_token(char *token,char *prev_token,COUNTER *count,COUNTER ploc); void check_for_function(char *token,char *prev_token); int keyword_compare(const char *word); int function_name_compare(char *word); void keyword_print(void); /************************************************************************** * * Function: main * * Description: Reads in a C program file and counts the number of * logical lines of code. Also displays each function * and displays the number of logical lines of code * for that function. * * Parameters: arcc - number of arguments passed into the program when * run from the command line. * argv - a pointer to each of the arguments passed into * the program from the command line. * * Return: none * **************************************************************************/ int main(int argc,char *argv[]) { COUNTER loc_count; /* number of logical lines of code */ COUNTER physical_loc; /* number of physical lines of code */ COUNTER comment_loc; /* number of comment lines of code */ COUNTER comment_nospace;/* count of white space */ COUNTER comment_char; /* count of total comment characters */ char filename[256]; /* C program to be counted filename */ FILE *file_ptr; /* C program file stream */ char last_char; /* the previous char read in from file */ char new_char; /* the current char read in from file */ char token[MAX_LINE_SIZE]; /* word in file */ char token1[MAX_LINE_SIZE]; /* used for tokenizing characters */ char token2[MAX_LINE_SIZE];/* another word in a file. */ char last_token[MAX_LINE_SIZE];/* previous token */ unsigned short token_len; /* length of the token string */ unsigned char comment; /* flag used for skipping stuff inside comments */ unsigned char quotation; /* flag used for skipping stuff inside quotes */ unsigned char single_quote;/* skip stuff inside single quotes */ unsigned char precompiler; /* skip pre-compiler defines */ unsigned char control_code;/* skip control codes started with \ */ unsigned char c_plus_plus_comment; /* flag used to discern comment type */ /* INITIALIZE */ new_char = 0; last_char = 0; token[0] = 0; token2[0] = 0; last_token[0] = 0; comment = FALSE; quotation = FALSE; single_quote = FALSE; precompiler = FALSE; control_code = FALSE; c_plus_plus_comment = FALSE; loc_count = 0; token_len = 0; physical_loc = 0; comment_loc = 0; comment_nospace = 0; comment_char = 0; Debug_Flag = FALSE; Interpret_Arguments(argc,argv); /* === COUNT LOGICAL LOC === */ /* open the file */ file_ptr = open_input_file(C_Filename); if (file_ptr == NULL) return 1; if (Debug_Flag) { debug_file_ptr = open_debug_file(); fprintf(debug_file_ptr,"Reading file: %s\n",C_Filename); } /* read the file one character at a time */ while ((new_char = fgetc(file_ptr)) != EOF) { /* count physical lines of code */ if (new_char == '\n') physical_loc++; /* COMMENT - skip until end of comment */ if (comment != FALSE) { /* count the number of characters in the comment */ comment_char++; /* conditions to end the comment */ if ((last_char == '*') && (new_char == '/')) { comment = FALSE; } /* End of line */ if (new_char == '\n') { /* conditions to end the comment */ if (c_plus_plus_comment != FALSE) { c_plus_plus_comment = FALSE; comment = FALSE; } /* count comment lines of code */ else { comment_loc++; } } /* count the number of whitespace chars in the comment */ if (!(isspace(new_char))) comment_nospace++; } /* end of comment */ /* QUOTES - skip until end of quotation */ else if (quotation != FALSE) { /* conditions to end the quotation */ if (control_code != FALSE) control_code = FALSE; else if (new_char == '\\') control_code = TRUE; else if (new_char == '"') quotation = FALSE; } /* SINGLE QUOTES - skip until end of quotes */ else if (single_quote != FALSE) { /* conditions to end the quotation */ if (control_code != FALSE) control_code = FALSE; else if (new_char == '\\') control_code = TRUE; else if (new_char == '\'') single_quote = FALSE; } /* PRE-COMPILER - skip until end of line but not \ eol */ else if (precompiler != FALSE) { /* conditions to end the pre compile */ if ((last_char != '\\') && (new_char == '\n')) precompiler = FALSE; } else { /* Turn on Comment Flag */ if (((new_char == '*') || (new_char == '/')) && (last_char == '/')) { if (new_char == '/') c_plus_plus_comment = TRUE; /* count comment lines of code */ comment_loc++; /* count the number of characters in the comment */ comment_char++; comment_char++; /* turn on flag to start looking for end of comment */ comment = TRUE; /* shrink token by 1 to remove / */ token_len = strlen(token); /* check to see if tokens are countable */ switch(token_len) { case 0: break; case 1: token[0] = 0; break; default: token[token_len-1] = 0; check_token(token,last_token,&loc_count,physical_loc); break; } } /* Turn on Quotation Flag */ else if (new_char == '"') { quotation = TRUE; check_token(token,last_token,&loc_count,physical_loc); } /* Turn on Single Quotation Flag */ else if (new_char == '\'') { single_quote = TRUE; check_token(token,last_token,&loc_count,physical_loc); } /* Turn on Pre-compiler Flag */ else if (new_char == '#') { precompiler = TRUE; sprintf(token2,"%c",new_char); check_token(token2,last_token,&loc_count,physical_loc); } /* Force token check - EOL */ else if (new_char == '\n') check_token(token,last_token,&loc_count,physical_loc); /* Force token check - WHITE SPACE */ else if (isspace(new_char)) check_token(token,last_token,&loc_count,physical_loc); /* Force token check - PUNCTUATION */ else if (ispunct(new_char)) { /* VALID NON-DELIMITER */ if ((new_char == '_') || (new_char == '~')) /* used in c++ destructors */ { /* valid character - include with token */ sprintf(token1,"%s%c",token,new_char); strcpy(token,token1); } /* DELIMITER FOUND */ else { check_token(token,last_token,&loc_count,physical_loc); /* check punct to see if it is a countable token */ sprintf(token2,"%c",new_char); check_token(token2,last_token,&loc_count,physical_loc); } /* end of token delimiter */ } /* BUILD TOKEN */ else { sprintf(token1,"%s%c",token,new_char); strcpy(token,token1); } } /* update any previous variables */ last_char = new_char; } /* close the file */ fclose(file_ptr); if (Debug_Flag) { fprintf(debug_file_ptr,"%-32s %6lu\n","PROGRAM TOTAL",loc_count); fclose(debug_file_ptr); } /* Print the results */ print_functions(C_Filename,loc_count,physical_loc,comment_loc); /* House Keeping */ delete_elements(); return 0; } /************************************************************************** * * Function: create_list_element * * Description: Allocates memory for a linked list element and returns * a pointer to that memory. * * Parameters: none * * Globals: none * * Locals: typedef of ELEMENT. * * Return: p - pointer to the memory allocated for that element. * **************************************************************************/ ELEMENT *create_list_element(void) { ELEMENT *p; p = (ELEMENT *) malloc( sizeof(ELEMENT)); if (p==NULL) { printf("create_list_element: malloc failed.\n"); exit(1); } p->next = NULL; return p; } /* end of function */ /************************************************************************** * * Function: add_element * * Description: Attaches an ELEMENT to the tail end of the linked list * by attaching it to the first ELEMENT that is NULL. * * Parameters: e - reference of ELEMENT e. * * Globals: none * * Locals: typedef of ELEMENT * head - first ELEMENT of the linked list * * Return: none * **************************************************************************/ void add_element(ELEMENT *e) { ELEMENT *p; /* if the first element has not been created, create it now */ if (head == NULL) { head = e; return; } /* otherwise, find the last element in the list */ for (p=head;p->next != NULL;p=p->next) {} p->next = e; return; } /************************************************************************** * * Function: delete_elements * * Description: De-allocates memory for all linked list elements starting with * head. * * Parameters: none * * Globals: none * * Locals: typedef of ELEMENT * head - first ELEMENT of the linked list * * Return: none * **************************************************************************/ void delete_elements(void) { ELEMENT *current; ELEMENT *next; current = head; while(current != NULL) { next = current->next; free(current); current = next; } return; } /************************************************************************** * * Function: print_functions * * Description: Prints all linked list elements starting with head. * * Parameters: none * * Globals: none * * Locals: typedef of ELEMENT * head - first ELEMENT of the linked list * * Return: none * **************************************************************************/ void print_functions(char *filename,COUNTER loc,COUNTER ploc,COUNTER cloc) { ELEMENT *current = NULL; COUNTER floc = 0; /* function line of code */ char *str = NULL; char *name = NULL; COUNTER methods = 0; /* Find the last token - that is the actual filename */ str = strtok(filename,":\\"); while (str != NULL) { name = str; str = strtok(NULL,":\\"); } printf("Program Function Function Total\n"); printf("Name Name LOC LOC\n"); printf("============ ================================ ======== ========\n"); if (name != NULL) printf("%s\n",name); else printf("\n"); current = head; floc = 0; while(current != NULL) { if (current->loc_count > 0) { printf("%-12s %-32s %8lu\n"," ",current->name,current->loc_count); floc += current->loc_count; methods++; } current = current->next; } printf(" -------- \n"); printf("TOTAL %-8lu %8lu %8lu", methods,floc,loc); printf("\n"); printf("============ ================================ ======== ========\n"); printf("%-12s %-32s %-8s %8lu\n","Physical LOC"," "," ",ploc); printf("%-12s %-32s %-8s %8lu\n","Comment LOC"," "," ",cloc); return; } /************************************************************************** * * Function: last_element * * Description: Returns a pointer to the last element of the list. If the * list is empty, it returns the NULL pointer. * * Parameters: none * * Globals: none * * Locals: typedef of ELEMENT. * head - first ELEMENT of the linked list * * Return: p - pointer to the last element. * **************************************************************************/ ELEMENT *last_element(void) { ELEMENT *p; /* if the first element has not been created, return NULL */ if (head == NULL) { p = head; } /* otherwise, find the last element in the list */ else { for (p=head;p->next != NULL;p=p->next) {} } return p; } /* end of function */ /************************************************************************** * * Function: open_input_file * * Description: Opens a file stream for input (read only) and returns a * file pointer to that stream. * * Parameters: filename - string containing the name of the file to be * opened. * * Globals: none * * Locals: none * * Return: fp - pointer to the stream of the file opened. * **************************************************************************/ FILE *open_input_file(char *filename) { FILE *fp; fp = fopen(filename,"r"); if (fp == NULL) printf("open_input_file: error opening %s.\n",filename); return fp; } /************************************************************************** * * Function: check_token * * Description: Compares tokens that contain something to the keywords and * increments a counter if there is a match. * * Parameters: token - reference to a string that contains some characters. * prev_token - reference to a string that gets loaded with the * token. * count - reference to a counter that gets incremented upon a * match. * * Globals: none * * Locals: keyword_compare function. * * Return: none * **************************************************************************/ void check_token(char *token,char *prev_token,COUNTER *count,COUNTER ploc) { char string[MAX_LINE_SIZE]; /* word in file */ if (token[0] != 0) { check_for_function(token,prev_token); strcpy(prev_token,token); if (keyword_compare(token)) { (*count)++; if (Debug_Flag) { strcpy(string,token); fprintf(debug_file_ptr,"Line %04lu => %s\n",ploc,string); } } token[0] = 0; } } /************************************************************************** * * Function: check_for_function * * Description: Looks for a last token that is not a reserved word, punctuation, * or digit, and a token that is a '('. If this is found, then the * last token,which should contain the function name, is loaded * into a linked list. The countable tokens are counted until * the brace level returns to 0. This is saved with the function * name in a linked list. * * Parameters: token - reference to a string that contains some characters. * prev_token - reference to a string that gets loaded with the * token. * count - reference to a counter that gets incremented upon a * match. * * Globals: none * * Locals: function_name_compare function. * * Return: none * **************************************************************************/ void check_for_function(char *token,char *prev_token) { static ELEMENT *temp_node = {NULL}; static COUNTER loc_count = {0}; static unsigned char count_flag = {FALSE}; static unsigned char start_flag = {FALSE}; static COUNTER brace_count = {0}; static COUNTER parenthesis_count = {0}; /* if a '(' is found, and last token is not a keyword, then load the function name, turn on the flag */ /* === Function flag is not set === */ if ((start_flag == FALSE) && (brace_count == 0)) { if (strcmp(token,"(") == 0) { if (function_name_compare(prev_token)) { /* create element and load list */ temp_node = create_list_element(); /* safe string copy - in case the token is very large. */ strncpy(temp_node->name,prev_token,MAX_FUNCTION_NAME); /*(temp_node->name+MAX_FUNCTION_NAME-1)=0;*/ temp_node->loc_count = 0; loc_count = 0; add_element(temp_node); start_flag = TRUE; parenthesis_count = 1; if (Debug_Flag) { fprintf(debug_file_ptr,"Possible Function=> %s\n",prev_token); } } } /* end of function start */ } /* end of no function flag */ /* === Function flag is set, but not a real function yet === */ else if (count_flag == FALSE) { if (strcmp(token,"(") == 0) parenthesis_count++; else if (strcmp(token,")") == 0) { if (parenthesis_count != 0) parenthesis_count--; } if (Debug_Flag) { fprintf(debug_file_ptr,"Function Set, Parenthesis Level=> %lu " "LOC Count=>%lu\n", parenthesis_count,loc_count); } if ((strcmp(prev_token,")") == 0) && (parenthesis_count == 0)) { /* Look for end of function call or prototype */ if (strcmp(token,";") == 0) { /* reset the function to look for new function */ start_flag = FALSE; } /* Look for end of function */ else if (strcmp(token,"{") == 0) { /* found valid function - start counting lines */ count_flag = TRUE; brace_count = 1; } } /* end of normal end parenthesis */ /* Look for start of 'old' style of functions */ else if ((strcmp(prev_token,";") == 0) && (parenthesis_count == 0)) { if (strcmp(token,"{") == 0) { /* found valid function - start counting lines */ count_flag = TRUE; brace_count = 1; } } /* end of old style function */ /* Count valid, countable tokens, including the stuff in the function call during this preliminary stage */ if (keyword_compare(token)) loc_count++; } /* end of function flag set */ /* === Function flag is set and started counting === */ else if ((count_flag != FALSE) && (start_flag != FALSE)) { if (strcmp(token,"{") == 0) brace_count++; else if (strcmp(token,"}") == 0) brace_count--; if (Debug_Flag) { fprintf(debug_file_ptr,"Function Set, Brace Level=> %lu " "LOC Count=>%lu\n", brace_count,loc_count); } /* Count valid, countable tokens, including the last brace */ if (keyword_compare(token)) loc_count++; /* Found the end of Function Method */ if (brace_count == 0) { /* turn off the function counter */ count_flag = FALSE; start_flag = FALSE; /* load the linked list with the results */ temp_node->loc_count = loc_count; } } /* end of function flag set and count flag set */ } /* end of function */ /************************************************************************** * * Function: function_name_compare * * Description: Compares a string with a list of valid strings and checks * for a match. Also checks for a punctuation or digit if * it is only a digit. * * Parameters: word - reference to a string that contains some characters. * * Globals: none * * Locals: c_keywords - structure containing C reserved words * * Return: status - FALSE if the reserved word or punct match is found. * TRUE if no match is found. * **************************************************************************/ int function_name_compare(char *word) { int status = TRUE; /* FALSE if reserve word or punct found */ int key_index = 0; /* index into the keyword structure */ if (strlen(word) > 1) { for (key_index=0;key_index < Max_Keywords;key_index++) { if (strcmp(word,c_keywords[key_index].data) == 0) status = FALSE; } } else if (ispunct(word[0])) status = FALSE; else if (isdigit(word[0])) status = FALSE; return status; } /************************************************************************** * * Function: keyword_compare * * Description: Compares a string with a list of valid strings and checks * for a match. * * Parameters: word - reference to a string that contains some characters. * * Globals: none * * Locals: c_keywords - structure containing C keywords * Max_Keywords - total number of keywords * * Return: status - TRUE if the keyword match is found. * FALSE if no match is found. * **************************************************************************/ int keyword_compare(const char *word) { int status = FALSE; /* TRUE if keyword match found */ int key_index = 0; /* index into the keyword structure */ for (key_index=0;key_index < Max_Keywords;key_index++) { if (c_keywords[key_index].valid_flag) { if (strcmp(word,c_keywords[key_index].data) == 0) status = TRUE; } } return status; } /************************************************************************** * * Function: keyword_print * * Description: Prints a list of valid strings on the screen 5 across. * * Parameters: none * * Globals: none * * Locals: c_keywords - structure containing C keywords * Max_Keywords - total number of keywords * * Return: none * **************************************************************************/ void keyword_print(void) { int key_index = 0; /* index into the keyword structure */ int count = 0; /* counter that counts number of words across screen */ for (key_index=0;key_index < Max_Keywords;key_index++) { if (c_keywords[key_index].valid_flag) { printf("%s",c_keywords[key_index].data); count++; if (count > 4) { printf("\n"); count = 0; } else printf("\t"); } } return; } /************************************************************************** * * Function: open_debug_file * * Description: Opens a file stream for output and returns a * file pointer to that stream. * * Parameters: none * * Globals: none * * Locals: none * * Return: fp - pointer to the stream of the file opened. * **************************************************************************/ FILE *open_debug_file(void) { FILE *fp; char filename[256]; char *date_buffer; /* Create a date string file name */ date_buffer = debug_file_date(); sprintf(filename,"%s.dbg",date_buffer); fp = fopen(filename,"w"); if (fp == NULL) printf("open_debug_file: error opening %s.\n",filename); else printf("open_debug_file: opened debug file %s.\n",filename); return fp; } /************************************************************************** * * Function: debug_file_date * * Description: Creates a string that will be the name of the debug file * using the current date. * * Parameters: none * * Globals: none * * Locals: none * * Return: fp - pointer to the stream of the file opened. * **************************************************************************/ char *debug_file_date(void) { static char time_buffer[80] = {""}; time_t timesec; struct tm *currtime; timesec = time(NULL); currtime = localtime(×ec); /* filename string to be YYYYMMDD */ strftime(time_buffer,sizeof(time_buffer),"%Y%m%d",currtime); return time_buffer; } /****************************************************************** * NAME: Interpret_Arguments * DESCRIPTION: Takes one of the arguments passed by the main function * and sets flags if it matches one of the predefined args. * PARAMETERS: argc (IN) number of arguments. * argv (IN) an array of arguments in string form. * GLOBALS: none * RETURN: none * ALGORITHM: none * NOTES: none * ******************************************************************/ void Interpret_Arguments(int argc, char *argv[]) { int i = 0; char *p_arg = NULL; if (argc < 2) { Usage(argv[0]); exit(1); } /* skip 1st one - its the command line for the filename */ for (i=1;i