#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
/*---------------------------------------------------------------------------*/
/* */
/* Copyright (C) 1998 - 2006 */
/* University of Southern California Center for Software Engineering */
/* Salvatori 330, 941 West 37th Place, */
/* Los Angeles, California 90089-0781, USA */
/* */
/* This program is free software with limitations; you can redistribute */
/* it and/or modify it under the terms of the USC-CSE Limited Public */
/* License as published by the University of Southern California */
/* Center for Software Engineering; either version 1 of the License, */
/* or (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* USC-CSE Limited Public License for more details. */
/* */
/* You should have received a copy of the USC-CSE Limited Public License */
/* along with this program; if not, write to: */
/* University of Southern California */
/* Center for Software Engineering */
/* Salvatori 300, 941 West 37th Place */
/* Los Angeles, California 90089-0781, USA. */
/* */
/*---------------------------------------------------------------------------*/
/* */
/* Original Software Product developed by the Northrop Grumman Corporation */
/* Electronic Sensors and Systems Sector (ES3) and provided to the */
/* University of Southern California (USC) Center for Software */
/* Engineering (CSE) via license to distribute. */
/* */
/*---------------------------------------------------------------------------*/
/* USC CSE UPDATES & REVISIONS */
/* */
/* REVISION DATE AUTHOR MODIFICATION */
/* Rev-1 9/09/98 GEK Transferred via License Agreement to the */
/* Center for Software Engineering at the */
/* University of Southern California. */
/* Version EG17, SWA-91-020, 1991-1998. */
/* */
/* Rev-2 2/19/99 GEK Corrected assignment of returned value from */
/* fgetc from a char to that of an int. This */
/* effects all occurrences of 'list_ch', */
/* 'list_int', 'ch', and 'lch'. */
/* Updated all checks for EOF to be compared */
/* to the integer value returned from fgetc vs.*/
/* the char value. */
/* */
/* Rev-3 3/21/00 GEK Added EXIT_SUCCESS to return statement of */
/* main and defined main to be of type int. */
/* Modified "NAME_LIST" define statements with */
/* improved continuation syntax. */
/* Modified file extension detection code to */
/* identify '.hh', and '.hpp' files as */
/* source code files. */
/* Changed delimiter that signifies a comment */
/* that was commenced on a previous line but */
/* continues across new lines from '/*' */
/* starting in line[0] to a '+' placed in */
/* line[0]. */
/* */
/* Rev-4 11/15/00 GEK Changed 'boolean' to 'bool_type' and defined */
/* enumeration types 'true' and 'false' as */
/* 'True' and 'False' so as not to conflict */
/* 'bool' typedef in C++. */
/* Updated description of commands used to */
/* create the c_list.dat file */
/* (see EXECUTION PROCEDURES, step 1). */
/* Replaced static with extern in all functions.*/
/* Updated transfer_file_name function. */
/* Corrected miscounting of comments when a */
/* slash-asterisk-slash triplet is encountered.*/
/* */
/* Rev-5 1/07/01 GEK Updated get_list_file_size function. */
/* Updated extension function. */
/* */
/* Rev-6 7/09/01 GEK Inserted check for left paren. following */
/* IF and FOR keywords in special processing. */
/* Inserted fclose for outfile.dat file. */
/* Added Word Wrap processing. */
/* Added LINE_WRAP error condition. */
/* Increased MAX_LINE_LENGTH from 132 to 264. */
/* Added 'lf_2' local flag. */
/* Updated get_list_file_size function. */
/* */
/* Rev-7 8/22/01 GEK Inserted check for left paren. following */
/* WHILE keyword in special processing. */
/* Renamed 'num_FOR_IF' to 'num_FOR_IF_WHILE'. */
/* */
/* Rev-8 7/28/03 GEK Check for an empty file before processing. */
/* Correction to Extension function. */
/* Added code to differentiate a double slash */
/* comment delimiter from a series of */
/* asterisk-slash slash-asterisk delimiters. */
/* Ignore a single string delimiter within a */
/* comment delimited by the double-slash. The */
/* error only occurs for languages that */
/* delimit comments using both a matching set */
/* of delimiters AND a separate delimiter */
/* where the comment terminates with the EOLN. */
/* */
/* Rev-9 4/08/06 Aditya Updated MAX_DIRR_TARGETS and DIRR_NAME_LIST */
/* Kulkarni to include the counting of #import and */
/* #using preprocessor directives */
/* */
/* Rev-10 5/16/06 VN Updated the code to make sure 'lch' is */
/* assigned before being referenced */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* USING ORGANIZATION UPDATES & REVISIONS */
/* */
/* REVISION DATE AUTHOR MODIFICATION */
/* Rev-A 9/09/98 USC CSE Release of the USC Distribution config. */
/* */
/* Rev-B ?/??/?? */
/* */
/*---------------------------------------------------------------------------*/
/* This program will count the number of source lines of code within a */
/* C or C++ source code file. The input to this program will be a file */
/* named 'c_list.dat', which contains the full directory and file name */
/* of the C/C++ source files of which will be read. Every file name */
/* pointed to by 'c_list.dat' will be accessed with readonly privilege. */
/* The output of this program will be found in the file 'c_outfile.dat'. */
/* */
/* Refer to the instructions that follow for further information on */
/* the installation and use of this code counting tool. */
/* */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* */
/* BASIC ASSUMPTIONS & DEFINITIONS */
/* */
/* o FILE EXTENSIONS : Files that contain C/C++ source code shall have a */
/* '.C', '.CC', '.CPP', '.H', '.HH', or '.HPP' file extension. */
/* Files without these file extensions are considered to be data files. */
/* The names of files are read/accessed without case sensitivity. */
/* The file version number and ';' when absent shall result in the highest */
/* version of that file to be analyzed. */
/* */
/* o DATA FILES : Data files shall contain only blank lines and data lines. */
/* Data lines shall be counted using the physical SLOC definition. */
/* */
/* o SOURCE FILES : Source code files may contain blank lines, comment */
/* lines (whole or embedded), compiler directives, data lines, or */
/* executable lines. */
/* Source code files to be analyzed shall have previously been compiled */
/* successfully to ensure the integrity of the inclusive syntax. */
/* */
/* o SLOC DEFINITION : The primary definitions for a Source Line of Code */
/* (SLOC) include the physical SLOC and the logical SLOC. */
/* The physical SLOC definition uses the Deliverable Source Instruction */
/* (DSI) concept. */
/* The logical SLOC definition is highly dependent upon the structure of */
/* the programming language to be parsed by the CodeCount tool. */
/* */
/* o PHYSICAL SLOC : The number of physical SLOCs within a source file is */
/* defined to be the sum of the number of physical SLOCs (terminated by */
/* a carriage return or EOLN character) which contain program instructions*/
/* created by project personnel and processed into machine code by some */
/* combination of preprocessors, compilers, interpreters, and/or */
/* assemblers. It excludes comment cards and unmodified utility software.*/
/* It includes job control language (compiler directive), format */
/* statements, and data declarations (data lines). Instructions are */
/* defined as lines of code or card images. Thus, a line containing */
/* two or more source statements count as one physical SLOC; a five line */
/* data declaration counts as five physical SLOCs. */
/* The physical SLOC definition was selected due to (1) compatibility with */
/* parametric software cost modeling tools, (2) ability to support */
/* software metrics collection, and (3) programming language syntax */
/* independence. */
/* */
/* o LOGICAL SLOC : The number of logical SLOC within a source file is */
/* defined to be the sum of the number of logical SLOCs classified as */
/* compiler directives, data lines, or executable lines. It excludes */
/* comments (whole or embedded) and blank lines. Thus, a line containing */
/* two or more source statements count as multiple logical SLOCs; a */
/* single logical statement that extends over five physical lines count */
/* as one logical SLOC. */
/* Specifically, the logical SLOC found within a file containing software */
/* written in the C/C++ programming language may be computed by summing */
/* together the count of (1) the number of terminal semicolons, (2) the */
/* number of end block statements, i.e., '}', (3) the number of FOR, IF */
/* and WHILE statements that do not have a block statement structure, and */
/* (4) the number of logical compiler directives. */
/* The logical SLOC definition was selected due to (1) compatibility with */
/* parametric software cost modeling tools, and (2) ability to support */
/* software metrics collection. */
/* The logical SLOC count is susceptible to erroneous output when the */
/* analyzed source code file contains software that uses overloading or */
/* replacement characters for a few key symbols, e.g., ';' . */
/* */
/* o TAB : A Tab character shall be replaced with a blank character upon */
/* input. */
/* */
/* o FORMFEED : A FormFeed character shall be replaced with a blank */
/* character upon input. */
/* */
/* o BLANK LINE : A blank line is defined as any physical line of the */
/* source file that contains only blank, Tab, or FormFeed characters */
/* prior to the occurrence of a carriage return (EOLN). */
/* */
/* o CHARACTER LITERALS : The contents of any character literals shall be */
/* overwritten with a special character prior to the search for comments */
/* so as not to interfere with the detection of comment delimiters. */
/* Specifically, any character literal designated by a matching set of */
/* single quote characters shall be overwritten. */
/* */
/* o ESCAPE SEQUENCES : Any escape sequences shall be overwritten with a */
/* special character prior to the search for comments or string literals */
/* so as not to interfere with the search for comment or string */
/* deliminters. */
/* Specifically, Only the \' and \" escape sequence shall be overwritten. */
/* */
/* o STRING LITERALS : The contents of any string literals shall be */
/* overwritten with a special character so as not to interfere with the */
/* detection of keywords or other programming language specific */
/* delimiters. */
/* Specifically, any string literal designated by a matching set of */
/* double quotes shall be overwritten. */
/* */
/* o COMMENTS : A comment is defined to be of two possible classifications, */
/* whole line or embedded. */
/* */
/* o WHOLE COMMENT : A whole line comment is defined as any string of */
/* characters which follow the programming language specific comment */
/* delimiter and as such does not co-exist on the same physical line with */
/* compilable source code. */
/* Specifically, a whole line comment is designated by the a slash-asterisk*/
/* and asterisk-slash pair of delimiters. A C++ whole line comment is */
/* designated by a double slash and continues until the carriage return */
/* (EOLN). */
/* Multiple whole line comments that co-exist on the same physical line */
/* shall be counted as a single whole line comment. */
/* Continuations of a whole line comment over multiple physical lines */
/* shall be individually classified and counted as either whole line or */
/* embedded comments in accordance with the definitions. */
/* */
/* o EMBEDDED COMMENT : An embedded comment is defined as any comment string */
/* that co-exists on the same physical line with compilable source code. */
/* Specifically, an embedded comment is designated using the same method */
/* as a whole line comment. */
/* Multiple embedded comments that co-exist of the same physical line */
/* with compilable source code shall be individually counted. */
/* The contents of embedded comments shall be blanked so as not to */
/* interfere with the detection of keywords or other programming language */
/* specific delimiters. */
/* Continuations of an embedded comment over multiple physical lines shall */
/* be individually classified and counted as either whole line or */
/* embedded comments in accordance with the definitions. */
/* */
/* o COMPILER DIRECTIVE : A compiler directive is defined as any line */
/* of code which contains one (or more) of the programming language */
/* specific directive keywords as found within the 'DIRR_NAME_LIST' */
/* constant. */
/* Specifically, the '#' symbol, i.e., DIRR_PREFIX, followed by any number */
/* of spaces (blanks) followed by an entry within the 'DIRR_NAME_LIST' */
/* constant defines the SLOC to be a compiler directive. A compiler */
/* directive terminates with a carriage return (EOLN). */
/* Continuation of a compiler directive over multiple physical lines of */
/* the file shall increment the physical SLOC count accordingly until a */
/* physical line is determined to be of another classification, e.g., */
/* data line or executable line. */
/* Continuation of a compiler directive over multiple physical lines of */
/* the file shall NOT increment the logical SLOC count. */
/* Multiple logical SLOC on the same physical line shall increment the */
/* logical SLOC count accordingly. */
/* A blank line or comment (whole or embedded) shall not cause the */
/* re-classification of a continuation of a compiler directive line. */
/* A compiler directive shall not exist within a data file. */
/* */
/* o DATA LINE : A data line is defined as any line of code which */
/* contains one (or more) of the programming language specific data */
/* keywords as found within the 'DATA_NAME_LIST' constant. */
/* Continuation of the data line over multiple physical lines of */
/* the file shall increment the physical SLOC count accordingly until a */
/* physical line is determined to be of another classification, e.g., */
/* directive or executable line. */
/* Continuation of the data line over multiple physical lines of */
/* the file shall NOT increment the logical SLOC count. */
/* Multiple logical SLOC on the same physical line shall increment the */
/* logical SLOC count accordingly. */
/* A blank line or comment (whole or embedded) shall not cause the */
/* re-classification of a continuation of a data line. */
/* A data line as found within the data file is defined as any physical */
/* line of code which is not a blank line. */
/* */
/* o EXECUTABLE LINE : An executable line is defined as any line of code */
/* which contains one (or more) of the programming language specific */
/* executable keywords as found within the 'EXEC_NAME_LIST' constant */
/* AND/OR has not been classified as a compiler directive or data line. */
/* Continuation of the executable line over multiple physical lines of */
/* the file shall increment the physical SLOC count accordingly until a */
/* physical line is determined to be of another classification, e.g., */
/* directive or data line. */
/* Continuation of an executable line over multiple physical lines of */
/* the file shall NOT increment the logical SLOC count. */
/* Multiple logical SLOC on the same physical line shall increment the */
/* logical SLOC count accordingly. */
/* A blank line or comment (whole or embedded) shall not cause the */
/* re-classification of a continuation of a executable line. */
/* An executable line shall not exist within a data file. */
/* */
/* o TOTAL SIZING: The total sizing of analyzed source code files in terms */
/* the SLOC count contains the highest degree of confidence. However, */
/* the sizing information pertaining to the subclassifications (compiler */
/* directives, data lines, executable lines) has a somewhat lower level */
/* of confidence associated with them. Missclassifications of the */
/* subclassifications of SLOC may occur due to (1) user modifications to */
/* the CodeCount tool, (2) syntax and semantic enhancements to the parsed */
/* programming language, (3) exotic usage of the parsed programming */
/* language, and (4) integrity of the host platform execution environment.*/
/* Additionally, in some programming languages a single SLOC may contain */
/* attributes of both a data declaration and an executable instruction */
/* simultaneously. These occurrences represent events beyond the control */
/* of the CodeCount tool designer and may cause the inclusive parsing */
/* capabilities of the tool to missclassify a particular SLOC. For these */
/* reasons, the counts of subclassifications should be regarded as an */
/* approximation and not as a precise count. In only the physical SLOC */
/* definition does the sum of the subclassification counts equal the */
/* total physical SLOC count. */
/* */
/* o KEYWORD COUNT : The search for any programming language specific */
/* keywords over a physical line of code for purposes of incrementing */
/* the tally of occurrences shall include the detection of multiple */
/* keywords of the same type, e.g., two occurrence of the keyword READ */
/* on the same physical line. */
/* The search for any programming language specific keywords over a */
/* physical line of code for purposes of incrementing the tally of */
/* occurrences shall include the detection on multiple keywords of */
/* different types, e.g., occurrences of keywords READ and WRITE on the */
/* same physical line. */
/* Keywords found within comments (whole or embedded) or string literals */
/* shall not be included in the tally count. */
/* */
/* o KEYWORDS SEARCH : Programming language specific keywords as contained */
/* within the 'NAME_LIST' constants may have any character other than */
/* 'A'..'Z', 'a'..'z', '0'..'9', '_', or '$' adjacent to it. This is */
/* used to differentiate keywords from other source code identifiers, */
/* e.g., READ versus READer versus you_READ. */
/* Characters contained in the SPECIAL set shall be blanked prior to the */
/* search for keywords to ensure that a space (blank) is located adjacent */
/* to all keywords and identifiers. */
/* */
/* o SPECIAL SET : The contents of the 'SPECIAL' set shall not include */
/* characters that are involved in search mechanisms which are */
/* executed following the elimination of the 'special' characters. */
/* */
/* o NAME_LIST ENTRIES : Keywords that appear in the 'NAME_LIST's that are */
/* multiple words, e.g., END IF, may have any amount (greater than one) */
/* of spaces (blanks) separating the component words. */
/* Multiple words, e.g., ELSE IF, must appear prior to occurrences of */
/* any of the components words within the NAME_LIST, e.g., ELSE and/or IF */
/* by themselves. */
/* */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* */
/* INSTALLATION PROCEDURES */
/* */
/* 1. Set the 'TARGET_REVISION' constant to the appropriate symbol to */
/* reflect the host platform environment that the CodeCount tool will */
/* execute upon. The current setting reflects a generic platform. */
/* */
/* 2. Set the 'DIRR_PREFIX' constant to the appropriate symbol to reflect */
/* the platform/language specific symbol that is used to indicate a */
/* compiler directive. Also, update the compiler directive prefix */
/* symbol for every entry in the 'DIRR_NAME_LIST' constant. */
/* */
/* 3. If user modifications to the CodeCount source file have been made, */
/* enter a description of the changes in the section labeled */
/* 'USING ORGANIZATION UPDATES & REVISIONS'. Set the 'USER_REVISION' */
/* constant to reflect the latest revision number. */
/* */
/* 4. Compile/Link the CodeCount tool using an ANSI-C compliant compiler. */
/* */
/* 5. Edit the 'c_lines_environment.dat' file to set the user definable */
/* parameters. These parameters include the name of the program/project */
/* that will be associated with the source code to be counted, along */
/* with other numeric quantities. A default value will be used in place */
/* of any incorrect numeric values read from this file. The default */
/* values are found in the function 'get_user_info' within this file. */
/* NOTE: If case sensitivity is enabled (Compare_Spec = 1), then the case */
/* of each entry contained within 'DIRR_NAME_LIST', 'DATA_NAME_LIST', */
/* 'EXEC_NAME_LIST' and arguments passed by the SEARCH procedure */
/* envoked in main must be adjusted in compliance with the prevailing */
/* coding standard for the source code to be analyzed. */
/* */
/* 6. Proceed to EXECUTION PROCEDURES. */
/* */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* */
/* EXECUTION PROCEDURES */
/* */
/* 1. Create the file 'c_list.dat' file. This file contains a list of */
/* each source file containing software to be counted. The format of */
/* this file is one filename (complete directory/path description) per */
/* physical line. The 'c_list.dat' file may be created by using one */
/* of the following commands : */
/* */
/* UNIX: */
/* ls -1 *.c >c_list.dat */
/* or, use the following to obtain full directory/pathname specification*/
/* find .-name '*.c' > c_list.dat */
/* to append this file with additional filenames use: */
/* find .-name '*.h' >> c_list.dat */
/* */
/* VAX VMS: */
/* Directory/noheading/notrailer/col=1/output=c_list.dat *.c */
/* to append this file with additional list file contents use: */
/* Append c_list1.dat, c_list2.dat c_list.dat */
/* */
/* MS-DOS: */
/* dir/B >c_list.dat *.c */
/* or, use the following to obtain full directory/pathname specification*/
/* along with files in all subdirectories: */
/* dir/B/S > c_list.dat *.c */
/* to append this file with additional filenames use: */
/* dir/B/S >> c_list.dat *.h */
/* */
/* 2. Execute the c_lines tool. A progress message may periodically */
/* appear on the terminal screen during execution. Error messages will */
/* appear on the terminal screen when abnormalities have been detected */
/* during execution. The duration of execution will be dependent upon */
/* the size and number of source files to be counted and the prevailing */
/* loading of the host platform. */
/* */
/* 3. An output file 'c_outfile.dat' is created and contains the output */
/* and any error messages generated during execution of the tool. */
/* */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* */
/* ERROR MESSAGES */
/* */
/* "ERROR, unable to open c_outfile.dat file" */
/* 1. The CodeCount tool is unable to open/create the output file. Check */
/* the privileges associated with file create for that directory. */
/* */
/* "ERROR, unable to open c_list.dat file" */
/* 1. 'c_list.dat' file does not exist in the current directory. */
/* 2. 'c_list.dat' file privileges prevent readonly access. */
/* */
/* "ERROR, unable to read c_list.dat file" */
/* 1. 'c_list.dat' file is an empty file. */
/* 2. 'c_list.dat' file is not in the correct format. */
/* */
/* "ERROR, truncated an entry of the c_list.dat file" */
/* 1. The 'c_list.dat' file contains a filename of length greater than */
/* 'MAX_LIST_FILENAME_LENGTH'. Increase the numerical value of */
/* the 'MAX_LIST_FILENAME_LENGTH' constant, then re-compile the tool. */
/* Since the input file cannot be accessed, the CodeCount tool will */
/* abort parsing of this file and proceed to the next source file */
/* specified in 'c_list.dat' file. */
/* */
/* "ERROR, unable to open c_lines_environment file" */
/* 1. 'c_lines_environment.dat' file does not exist in the current */
/* directory. */
/* 2. 'c_lines_environment.dat' file privileges prevent readonly access. */
/* */
/* "ERROR, error in reading c_lines_environment file" */
/* 1. 'c_lines_environment.dat' file contents is corrupted. */
/* 2. A numeric value contained within the 'c_lines_environment.dat' */
/* file exceed predefined bounds causing the default value to be used. */
/* */
/* "ERROR, unable to access file -> <filename>" */
/* 1. The input file does not exist at the directory/path location. */
/* 2. The directory/path specified is incorrect. */
/* 3. The directory/path location does not permit readonly access to files.*/
/* */
/* "ERROR, empty file -> <filename>" */
/* 1. The input file contains only an EOF marker. */
/* */
/* "ERROR, truncated a line of <filename>" OR */
/* "ERROR, truncated a line of file -> <filename>" */
/* 1. The input file contains a line of length less than or equal to the */
/* 'MAX_LINE_LENGTH' constant, but is also greater than the */
/* 'Line_Length' parameter within the 'c_lines_environment.dat' */
/* file. */
/* To prevent SLOC counting errors, the CodeCount tool will abort */
/* parsing of this file and proceed to the next source file specified */
/* in 'c_list.dat'. */
/* To correct this condition, either */
/* A. increase the value of the 'Line_Length' parameter within the */
/* 'c_lines_environment.dat' file, */
/* B. set the 'Line_Length' value to '0' within the */
/* 'c_lines_environment.dat' file to enable wordwrap processing, */
/* C. for UNIX systems, try using the following Korn shell command */
/* to correct for missing EOLN symbols. */
/* %tr -d ^M "\r" <file_name */
/* */
/* "ERROR, EOLN not detected in <filename>" OR */
/* "ERROR, EOLN not detected in file -> <filename>" */
/* 1. The input file contains a line of length greater than the */
/* 'MAX_LINE_LENGTH' constant. */
/* To prevent SLOC counting errors, the CodeCount tool will abort */
/* parsing of this file and proceed to the next source file specified */
/* in 'c_list.dat'. */
/* To correct this condition, either */
/* A. increase both the value of the 'Line_Length' parameter within */
/* the 'c_lines_environment.dat' file and the value of the */
/* MAX_LINE_LENGTH constant, */
/* B. set the 'Line_Length' value to '0' within the */
/* 'c_lines_environment.dat' file to enable wordwrap processing, */
/* C. for UNIX systems, try using the following Korn shell command */
/* to correct for missing EOLN symbols. */
/* %tr -d ^M "\r" <file_name */
/* */
/* "ERROR, Word Wrap processing error in <filename>" OR */
/* "ERROR, Word Wrap processing error in file -> <filename>" */
/* 1. The wordwrap processing has detected a non-comment SLOC that was */
/* concatenated to fit within 'line'. As such, keywords and other */
/* valuable code artifacts were lost. */
/* To prevent SLOC counting errors, the CodeCount tool will abort */
/* parsing of this file and proceed to the next source file specified */
/* in 'c_list.dat'. */
/* To correct this condition, either */
/* A. edit <filename> to correct the long SLOC statement, */
/* B. increase the value of the MAX_LINE_LENGTH constant. */
/* */
/* "ERROR, unable to open temp_file.dat" */
/* 1. The current directory/path location does not permit creation of */
/* files. */
/* */
/* "ERROR, Physical SLOC counting error in <filename>" OR */
/* "ERROR, Physical SLOC counting error in the following file" */
/* 1. Internal CodeCount tool logic has incorrectly processed source code */
/* within the input file. */
/* 2. The input file does not contain compilable source code resulting in */
/* misinterpretation of the source language constructs. */
/* */
/* "ERROR, Logical SLOC counting error in <filename>" OR */
/* "ERROR, Logical SLOC counting error in the following file" */
/* 1. Internal CodeCount tool logic has incorrectly processed source code */
/* within the input file. */
/* 2. The input file does not contain compilable source code resulting in */
/* misinterpretation of the source language constructs. */
/* */
/* "ERROR, unable to perform calculation" */
/* 1. Internal CodeCount tool logic has incorrectly processed source code */
/* within the input file. */
/* 2. Erroneous operands have been detected prior to performing a math */
/* calculation that will result in a run-time error. */
/* */
/* "ERROR, processing error detected in Search function" */
/* 1. A call to the Search function was made with erroneous input data. */
/* This may be caused by user modifications to the CodeCount tool. */
/* */
/*---------------------------------------------------------------------------*/
#define USER_REVISION 'A' /* User update revision letter. */
#define TARGET_REVISION 'G' /* Host platform identifier: U = UNIX, */
/* V = VAX11 VMS, A = VAX Alpha VMS, */
/* S = Sun, D = DOS, M = Macintosh, */
/* G = Generic (no specific platform) */
#define DEVELOPER_REVISION "10" /* Developer update revision number. */
#define LICENTIATE "USC CSE and COCOMO II Affiliates "
/* Name of purchaser for which the */
/* CodeCount License applies to. */
#define TOOL_PREFIX "c" /* File name prefix used with all files */
/* associated with this CodeCount tool. */
/* Should not exceed 12 characters. */
#define MAX_PROJECT_NAME 45 /* Max length of user-specified project */
/* name. */
#define MAX_LIST_FILENAME_LENGTH 132/* Number of characters to be read when */
/* parsing 'c_list'. Largest entry */
/* should not exceed a value of 132. */
#define MAX_FILENAME_LENGTH 58 /* Number of characters in the name */
/* of the input file. Largest entry */
/* should not exceed a value of 58. */
#define MAX_HEADER_LENGTH 74 /* Number of columns prior to output of */
/* the filename within 'c_outfile'. */
/* DO NOT change this constant! */
/* 132 cols <= MAX_FILENAME_LENGTH + */
/* MAX_HEADER_LENGTH */
#define MAX_LINE_LENGTH 264 /* Length of a source line to be */
/* read from an input file. */
#define MAX_WW_LINE_LENGTH 10 /* Length of a wordwrap buffer that is */
/* appended to end of 'line' when */
/* wordwrap feature is enabled. */
#define MAX_TEST_LENGTH 20 /* DO NOT change this constant! */
#define FF_CHAR '\f' /* This character is a Form Feed. */
#define TAB_CHAR '\t' /* This character is a TAB. */
#define CR_CHAR '\r' /* This character is a carriage retrun. */
#define QUOTE_CHAR '\'' /* This character is a single quote. */
#define MAX_TARGET_LENGTH MAX_TEST_LENGTH
/* Number of characters in a keyword. */
#define MAX_TARGETS 32 /* Maximum size of the 'NAME_LISTs. */
#define MAX_DIRR_TARGETS 16 /* The number of entries in the */
/* DIRR_NAME_LIST to be examined. */
#define MAX_DATA_TARGETS 32 /* The number of entries in the */
/* DATA_NAME_LIST to be examined. */
#define MAX_EXEC_TARGETS 31 /* The number of entries in the */
/* EXEC_NAME_LIST to be examined. */
#define MAX_STR_LENGTH MAX_TARGETS * (1 + MAX_TARGET_LENGTH)
/* Maximum STRing length to be passed */
/* in calls to load_names_and_tags. */
/* The "+1" is to account for the "*" */
/* used as a flag to indicate if the */
/* number of times that keyword */
/* appeared should be printed out. */
/* If the asterisk is not present the */
/* keyword is used to determine the */
/* type of line being read in. */
#define MAX_EXCLUDE_SET 2*26+10+2 /* Maximum number of characters to be */
/* included in 'exclude' set. */
#define MAX_SPECIAL_SET 22 /* Maximum number of characters to be */
/* included in 'special' set. */
#define CODE 0 /* Replaces 'file_mode_type', used in */
/* 'total_type' and */
#define DATA 1 /* 'file_mode_names_type'. */
#define PHY 0 /* Physical SLOC reference. */
#define LOG 1 /* Logical SLOC reference. */
#define BLANK ' '
#define BAR '-'
#define MAX_EOLN_TRIES 2*MAX_LINE_LENGTH
/* Maximum consecutive tries to detect */
/* newline before LINE* error is set. */
/* Active when wordwrap feature is off. */
#define DIRR_PREFIX '#' /* Prefix symbol delineating a directive.*/
/* Note: blanks and tabs located between */
/* the DIRR_PREFIX and the compiler */
/* directive identifier are extracted */
/* prior to comparison with entries */
/* with DIRR_NAME_LIST. */
/* Entries without the '*' prefix will */
/* not be included in searches. */
/* MAX_DIRR_TARGETS must be modified */
/* when entries are inserted or deleted.*/
/* MAX_DIRR_TARGETS and MAX_TARGETS must */
/* be modified when the length of this */
/* list is increased or decreased. */
/* Multiple word entries must appear */
/* prior to any single occurrence of a */
/* component word within this list, */
/* e.g., 'ELSE IF' must appear prior to */
/* 'ELSE' and 'IF'. */
#define DIRR_NAME_LIST \
"* #define "\
"* #undef "\
"* #if "\
"* #ifdef "\
"* #ifndef "\
"* #else "\
"* #elif "\
"* #endif "\
"* #include "\
"* #line "\
"* #pragma "\
"* #error "\
"* #dictionary "\
"* #module "\
"* #import "\
"* #using "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "\
" "
/* Entries without the '*' prefix will */
/* not be included in searches. */
/* MAX_DATA_TARGETS must be modified */
/* when entries are inserted or deleted.*/
/* MAX_DATA_TARGETS and MAX_TARGETS must */
/* be modified when the length of this */
/* list is increased or decreased. */
/* Multiple word entries must appear */
/* prior to any single occurrence of a */
/* component word within this list, */
/* e.g., 'ELSE IF' must appear prior to */
/* 'ELSE' and 'IF'. */
#define DATA_NAME_LIST \
"* FILE "\
"* const "\
"* bool "\
"* int "\
"* long "\
"* unsigned "\
"* short "\
"* char "\
"* wchar_t "\
"* float "\
"* double "\
"* enum "\
"* class "\
"* struct "\
"* union "\
"* void "\
"* typedef "\
"* auto "\
"* register "\
"* static "\
"* extern "\
"* namespace "\
"* asm "\
"* template "\
"* operator "\
"* mutable "\
"* friend "\
"* volatile "\
"* using "\
"* explicit "\
"* inline "\
"* virtual "
/* Entries without the '*' prefix will */
/* not be included in searches. */
/* MAX_EXEC_TARGETS must be modified */
/* when entries are inserted or deleted.*/
/* MAX_EXEC_TARGETS and MAX_TARGETS must */
/* be modified when the length of this */
/* list is increased or decreased. */
/* Multiple word entries must appear */
/* prior to any single occurrence of a */
/* component word within this list, */
/* e.g., 'ELSE IF' must appear prior to */
/* 'ELSE' and 'IF'. */
#define EXEC_NAME_LIST \
"* goto "\
"* if "\
"* else "\
"* for "\
"* do "\
"* while "\
"* continue "\
"* switch "\
"* case "\
"* break "\
"* default "\
"* return "\
"* entry "\
"* sizeof "\
"* new "\
"* delete "\
"* try "\
"* throw "\
"* catch "\
"* typeid "\
"* const_cast "\
"* static_cast "\
"* dynamic_cast "\
"* reinterpret_cast "\
"* stdin "\
"* stdout "\
"* stderr "\
"* cin "\
"* cout "\
"* cerr "\
"* clog "\
" "
FILE *c_lines_environment ; /* Contains User-Defined data*/
FILE *c_list ; /* Contains file names */
FILE *infile ; /* Input source files */
FILE *c_outfile ; /* Contains output info. */
typedef enum {False, True} bool_type ;
typedef char filename_type[MAX_FILENAME_LENGTH+1] ;
typedef char list_filename_type[132+1] ;
typedef char project_name_type[MAX_PROJECT_NAME+1] ;
typedef char test_type[MAX_TEST_LENGTH+1] ;
typedef char line_type[MAX_LINE_LENGTH+2+1] ;
typedef char ww_line_type[MAX_WW_LINE_LENGTH+1] ;
typedef char target_type[MAX_TARGET_LENGTH+1] ;
typedef target_type target_name_array_type[MAX_TARGETS] ;
/* Used to store the */
/* keywords. */
typedef long int target_length_array_type[MAX_TARGETS] ;
/* This array type will */
/* contain the lengths of */
/* the keywords, used in */
/* keyword searches */
typedef bool_type target_tag_array_type[MAX_TARGETS] ;
/* Arrays of this TAG type */
/* will be used to */
/* indicate which keywords */
/* are to be printed out */
/* in the output section. */
typedef long int target_tally_array_type[MAX_TARGETS] ;
/* This array type will be */
/* used to tally the */
/* occurrences of the key */
/* words. */
typedef char str_array_type[MAX_STR_LENGTH+1] ;
typedef char exclude_type[MAX_EXCLUDE_SET+1] ;
typedef char special_type[MAX_SPECIAL_SET+1] ;
typedef enum {YES, UNDEF, NO} new_boolean_type ;
typedef long int total_type[2][2] ;
/* 1st subscript: CODE = 0 */
/* DATA = 1 */
/* 2nd subscript: PHY = 0 */
/* LOG = 1 */
typedef long int tally_type[2] ;
/* 1st subscript: PHY = 0 */
/* LOG = 1 */
typedef enum {ANY, DIR, DAT, EXE} line_mode_type ;
typedef target_type file_mode_names_type[2] ;
typedef enum {OK ,
OUTFILE_OPEN ,
LISTFILE_OPEN ,
LISTFILE_READ ,
LISTFILE_TRUNC,
ENVFILE_OPEN ,
ENVFILE_READ ,
INFILE_OPEN ,
INFILE_EMPTY ,
LINE_TRUNC ,
LINE_SIZE ,
LINE_WRAP ,
TEMPFILE_OPEN ,
PHY_COUNT ,
LOG_COUNT ,
MATH_ERROR } error_type ;
extern void get_a_piece (char line[],
long int loc ,
long int length,
char test[] )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will extract a small piece of the characters contained */
/* within the array 'line', and place that piece into the array 'test'. */
/* */
/* Rev A-D 6/87- 9/96 Original Corrected 'IF' statement by */
/* Developer installing the <= and +1 feature. */
/* Installed 'length' parameter to */
/* be passed by the call. */
/* Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* */
/* Rev-E 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-F ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Get_A_Piece */
long int count ;
long int i ;
for (i = 0; i < MAX_TEST_LENGTH; i++) /* Clear test array */
test[i] = ' ';
if ((loc <= MAX_LINE_LENGTH - length) &&
(length <= MAX_TEST_LENGTH ) )
{ /* If */
count = 0;
for (i = loc; i < (loc + length); i++)
{ /* For */
test[count] = line[i];
count++;
} /* For */
} /* If */
} /* Get_A_Piece */
extern void do_upper_case (char line_char ,
char test_char ,
bool_type close_match,
long int *count_ptr )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will compare the upper case 'line_char' with either a */
/* an upper case 'test_char', or ( IF close_match = FALSE ) */
/* a lower case 'test_char' . */
/* IF close_match had been set to TRUE, then only an upper case to */
/* upper case comparison would be considered to be valid. */
/* */
/* Rev A-C 7/94- 9/96 Original Converted to ANSI-C and unit tested. */
/* Developer Removed redundant enum from boolean. */
/* Added prototype function headings. */
/* Added static void function prefix. */
/* */
/* Rev-D 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-E ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Do_Upper_Case */
#define OFFSET ('A' - 'a')
if ((line_char == test_char ) ||
((line_char == test_char - OFFSET) &&
(close_match == False ) ) )
(*count_ptr)++;
else
*count_ptr = 0;
#undef OFFSET
} /* Do_Upper_Case */
extern void do_lower_case (char line_char ,
char test_char ,
bool_type close_match,
long int *count_ptr )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will compare the lower case 'line_char' with either a */
/* a lower case 'test_char', or ( IF close_match = FALSE ) */
/* an upper case 'test_char' . */
/* IF close_match had been set to TRUE, then only an lower case to */
/* lower case comparison would be considered to be valid. */
/* */
/* Rev A-C 7/94- 9/96 Original Converted to ANSI-C and unit tested. */
/* Developer Removed redundant enum from boolean. */
/* Added prototype function headings. */
/* Added static void function prefix. */
/* */
/* Rev-D 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-E ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Do_Lower_Case */
#define OFFSET ('A' - 'a')
if ((line_char == test_char ) ||
((line_char == test_char + OFFSET) &&
(close_match == False ) ) )
(*count_ptr)++;
else
*count_ptr = 0;
#undef OFFSET
} /* Do_Lower_Case */
extern void search (char line[] ,
char test[] ,
long int start ,
long int stop ,
bool_type close_match,
long int line_length,
bool_type *flag_ptr ,
long int *where_ptr ,
long int position )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will scan the array 'line' until the string contained */
/* in the array 'test' is found. 'Flag' is returned as TRUE if a */
/* match was found, and FALSE if no match was found. */
/* */
/* Rev A-G 6/87-11/97 Original Revised to include matching of */
/* Developer words which may differ only in */
/* upper versus lower case letters. */
/* Included the capacity to compare */
/* a substring passed within 'test'. */
/* Extension of Search (old function) */
/* POSITION allows the search to */
/* begin from any location in the LINE. */
/* Added 'line_length' to argument list. */
/* Removed 'test_length' from WHILE */
/* condition to allow scan to EOLN. */
/* Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* Renamed function from New_Search. */
/* Deleted 'search_error' variable. */
/* Restructured 1st IF statement. */
/* Added check for null terminator in */
/* 'line' with a blank character in */
/* 'test'. */
/* */
/* Rev-H 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-I ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Search */
long int count ;
long int test_length ;
long int i ;
*flag_ptr = False;
*where_ptr = 0;
if ((start <= stop ) &&
(stop <= MAX_TEST_LENGTH) )
{ /* If start */
i = position;
count = 0;
test_length = stop - start + 1;
while ((i <= line_length + 1 ) &&
(*flag_ptr == False ) )
{ /* While */
if ((test[count + start] >= 'A') &&
(test[count + start] <= 'Z') )
do_upper_case(line[i], test[count + start], close_match, &count);
else
{ /* Else */
if ((test[count + start] >= 'a') &&
(test[count + start] <= 'z') )
do_lower_case(line[i], test[count + start], close_match, &count);
else
{ /* Else */
if ((line[ i ] != ' ') ||
(line[i+1] != ' ') ||
( count != 0 ) )
{ /* If */
if (line[i] == test[count + start])
count++;
else
if ((line[i] == '\0') &&
(test[count + start] == ' ' ) )
count++;
else
count = 0;
} /* If */
} /* Else */
} /* Else */
if (count == test_length)
{ /* If */
*flag_ptr = True;
*where_ptr = i - test_length + 1;
} /* If */
else
i++;
} /* While */
} /* If start */
else
printf("ERROR, processing error detected in Search function\n");
} /* Search */
extern void context_search (char line[] ,
char test[] ,
long int start ,
long int stop ,
bool_type close_match ,
long int line_length ,
bool_type *flag_ptr ,
long int *where_ptr ,
long int *where_end_ptr,
char exclude[] ,
long int position ,
bool_type white_out )
/*---------------------------------------------------------------------------*/
/* */
/* This procedure looks for a keyword in 'line' that is not followed by a */
/* character in the set 'EXCLUDE' . This procedure is a multiple step */
/* recursive procedure. When 'white_out' is set to true, this procedure */
/* will clear occurrences of 'test' from 'line' to support further */
/* searches. */
/* */
/* Rev A-E 7/87-11/97 Original Initial Development. */
/* Developer Allows for multiple words in TEST. */
/* Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* Added 'line_length' to argument list */
/* to increase throughput. */
/* Added check for null terminator as */
/* next character following a keyword. */
/* */
/* Rev-F 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-G ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Context_Search */
long int i, j, k;
long int m, n ;
long int s, t ;
j = 0; /* count the number of blanks*/
for (i = start; i <= stop; i++)
if (test[i] == ' ')
j++; /* For */
if (j <= 1) /* No blanks in the test */
{ /* If j<=1 */
search(line, test, start, stop, close_match, line_length,
flag_ptr, where_ptr, position);
/* Determine end location of */
*where_end_ptr = *where_ptr + stop - start; /* current word */
if (*flag_ptr == True) /* Check terminator of word */
{ /* If */
if (NULL != strchr(exclude, line[*where_end_ptr + 1]) )
*flag_ptr = False; /* Word is not a keyword. */
if (line[*where_end_ptr + 1] == '\0')
*flag_ptr = True ; /* Found keyword at EOLN. */
} /* If */
if ((*flag_ptr == True) && /* Remove keyword from 'line'*/
(white_out == True) ) /* to support future search.*/
for (m = *where_ptr; m <= *where_end_ptr; m++)
line[m] = ' ';
} /* If j<=1 */
else /* Multiple words have been */
{ /* detected, must parse each*/
i = start + 1; /* Search for a blank */
while ((i <= stop ) &&
(test[i] != ' ') )
i++;
/* Look for the next word */
j = i; /* in 'test' */
search(line, test, start, i - 1, close_match, line_length,
flag_ptr, where_ptr, position);
k = *where_ptr;
if (*flag_ptr == True)
{ /* If multiple words */
/* Ending position of */
s = k + i - start; /* found word */
/* Recursive call */
context_search(line, test, j, stop, close_match, line_length,
flag_ptr, &t, where_end_ptr, exclude, s, False);
if (*flag_ptr == True)
{ /* If flag_ptr */
n = 0;
for (m = s; m < t; m++)
if (line[m] != ' ')
n = 1;
if (n == 0) /* Only blanks inside */
{ /* If n==0 */
if (white_out == True) /* Blank out phrase */
for (m = *where_ptr; m <= *where_end_ptr; m++)
line[m] = ' ';
} /* If n==0 */
/* Failure: try for next */
/* occurrence using a */
/* recursive call */
else
context_search(line, test, start, stop, close_match, line_length,
flag_ptr, where_ptr, where_end_ptr, exclude,
s, white_out);
} /* If flag_ptr */
} /* If multiple words */
} /* Else */
} /* Context_Search */
extern void count_targets (char name_array[MAX_TARGETS][MAX_TARGET_LENGTH+1],
long int tally_array[] ,
long int length_array[],
long int num ,
char line[] ,
bool_type close_match ,
long int line_length ,
bool_type *found_ptr ,
long int *line_loc_ptr ,
char exclude[] )
/*---------------------------------------------------------------------------*/
/* */
/* This procedure will search through all words contained within the */
/* string 'line', and compare each word to the list of target words found */
/* within 'name_array'. If a match is found, then the number of */
/* occurrences of that particular word is incremented, 'tally_array', and */
/* the target word contained in 'line' is blanked so as not to be */
/* detected again due to the recursive nature of the search process. */
/* */
/* Rev A-C 12/90- 9/96 Original Added 'line_length' to argument list. */
/* Developer Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* */
/* Rev-D 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-E ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Count_Targets */
long int i ;
long int j ;
long int end_loc;
i = 0; /* Beginning of line */
while (i < line_length - 1) /* process whole line */
{ /* While */
while ((line[ i ] == ' ' ) && /* Move to one space */
(line[i+1] == ' ' ) && /* before the next word. */
( i < line_length - 1) )
i++;
if (i < line_length - 1)
{ /* If */
for (j = 0; j < num; j++) /* Consider all targets. */
{ /* For */
/* Only search if first */
/* character in target */
/* word is the same as */
/* that of the word in */
/* the line. */
if (toupper(line[i + 1]) == toupper(name_array[j][1]))
{ /* If */
context_search(line, name_array[j], 0, length_array[j] - 1,
close_match, line_length, found_ptr, line_loc_ptr,
&end_loc, exclude, i, True);
if (*found_ptr == True)
tally_array[j] = tally_array[j] + 1;
} /* If */
} /* For */
if (i < line_length - 1) /* Move to next location */
i++;
while ((line[i] != ' ' ) && /* Pass over current word */
(i < line_length - 1) )
i++;
} /* If */
} /* While */
} /* Count_Targets */
extern void load_name_and_tag_arrays (target_name_array_type name_array ,
target_tag_array_type tag_array ,
target_length_array_type length_array,
str_array_type str ,
long int num )
/*---------------------------------------------------------------------------*/
/* */
/* Loads the STR_ARRAY into slots in the NAME_ARRAY. */
/* Computes the LENGTH_ARRAY by counting the number of blanks at the end */
/* of the name and subtracting that number from MAX_TARGET_LENGTH. */
/* TAG_ARRAY is also computed. If an asterisk is in the first column, */
/* then the keyword is designated (TRUE) to be printed out; otherwise it */
/* is given the value (FALSE). Note: in either case the first column is */
/* not attached to the NAME_ARRAY. */
/* */
/* Rev A-C 7/87- 9/96 Original Initial Development. */
/* Developer Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* */
/* Rev-D 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-E ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Load_Name_And_Tag_Arrays */
long int i ;
long int j ;
long int offset ;
for (i = 0; i < num; i++)
{ /* For */
offset = i * (MAX_TARGET_LENGTH + 1) ; /* Compute offset to locate */
/* the '*' within 'str' */
if (str[offset] == '*') /* boolean to 'tag_array' */
tag_array[i] = True;
else
tag_array[i] = False;
for (j = 0; j < MAX_TARGET_LENGTH; j++) /* copy 'str' contents */
name_array[i][j] = str[offset + j + 1];
j = MAX_TARGET_LENGTH - 1; /* search for last blank */
while (( j > 0 ) &&
( name_array[i][j] == ' ' ))
j-- ;
length_array[i] = j + 1; /* no blank included at end */
} /* For */
} /* Load_Name_And_Tag_Arrays */
extern void clear_tally (long int tally_array[],
long int num )
/*---------------------------------------------------------------------------*/
/* */
/* Resets the TALLY_ARRAY [1..NUM] to 0. */
/* */
/* Rev A-C 7/87- 9/96 Original Initial Development. */
/* Developer Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* */
/* Rev-D 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-E ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Clear_Tally */
long int i;
for (i = 0; i < num; i++)
tally_array[i] = 0;
} /* Clear_Tally */
extern void write_dots (char str[MAX_TARGET_LENGTH],
FILE *outfile )
/*---------------------------------------------------------------------------*/
/* */
/* Takes the STR and fills up the blanks at its end with dots. */
/* */
/* Rev A-C 7/87- 9/96 Original Initial Development. */
/* Developer Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* Added 'outfile' to argument list. */
/* Local variables declared as long int. */
/* */
/* Rev-D 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-E ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Write_Dots */
long int i ;
long int j ;
/* Search right to left */
/* through 'str' until a */
j = MAX_TARGET_LENGTH - 1; /* non-blank character */
while (( j > 0 ) &&
(str[j] == ' ') )
j--;
j++; /* Move right one space */
for (i = 0; i < j; i++) /* Print contents of 'str' */
fprintf(outfile, "%c", str[i]);
for (i = j; i < MAX_TARGET_LENGTH; i++) /* Print remaining spaces */
fprintf(outfile, ".");
} /* Write_Dots */
extern void search_for_semi_colon (char line[] ,
long int line_length,
bool_type *flag_ptr ,
long int *num_ptr )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will search the 'line' for occurrences of a ';'. The */
/* 'flag_ptr' is set to true upon detection of the first ';'. The */
/* total number of detected ';'s is assigned to 'num_ptr'. */
/* */
/* Rev A-D 12/90-11/97 Original Added 'line_length' to argument list. */
/* Developer Converted to ANSI-C and unit tested. */
/* Added prototype function headings. */
/* Modified to return the number of ';'s */
/* detected in 'line'. */
/* */
/* Rev-E 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-F ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Search_For_Semi_Colon */
long int i;
*flag_ptr = False;
*num_ptr = 0 ;
for (i = 1; i <= line_length; i++)
{ /* For */
if (line[i] == ';')
{ /* If */
*flag_ptr = True;
(*num_ptr)++;
} /* If */
} /* For */
} /* Search_For_Semi_Colon */
extern void search_for_continuation (char line[] ,
long int line_length,
bool_type *flag_ptr )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will search for the C/C++ specific continuation characters */
/* within the 'line', i.e. '\' or a ',' as the last character. The */
/* rightmost embedded comments must have been cleared prior to execution */
/* of this function. */
/* */
/* Rev A-D 7/94-11/97 Original Convected to ANSI-C and unit tested. */
/* Developer Added prototype function headings. */
/* Changed >=1 to >0 in While conditional.*/
/* Added search for a ','. */
/* */
/* Rev-E 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-F ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Search_For_Continuation */
long int i;
i = line_length; /* Locate last non-blank char*/
while ((i > 0 ) &&
(line[i] == ' ') )
i--;
if ((line[i] == '\\') ||
(line[i] == ',' ) )
*flag_ptr = True ;
else
*flag_ptr = False;
} /* Search_For_Continuation */
extern void compress_directives (char line[] ,
char symbol ,
long int *length_ptr,
bool_type *flag_ptr )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will scan 'line' to locate occurrences of any compiler */
/* directives whereas there exists blank spaces between the prefix */
/* symbol and the name of the directive. The blank spaces will be */
/* eliminated thereby compressing the directive name and aiding in the */
/* search processes to follow. */
/* */
/* Rev A-B 8/96- 9/96 Original Created and unit tested. */
/* Developer Added prototype function headings. */
/* */
/* Rev-C 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-D ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Compress_Directives */
long int i ;
long int j ;
long int n ;
long int sum_n;
*flag_ptr = False;
i = 1;
sum_n = 0;
while (i <= *length_ptr + 1)
{ /* While */
if (line[i] == symbol)
{ /* If */
/* set flag indicating that */
/* a directive prefix */
*flag_ptr = True; /* has been detected. */
/* determine number of */
n = 0; /* blanks to eliminate. */
j = i + 1;
while ((j <= *length_ptr + 1) &&
( line[j] == ' ' ) )
{ /* While */
j++;
n++;
} /* While */
if (n > 0) /* detected blanks. */
{ /* If */
j = i + 1;
while (j <= (*length_ptr - n + 1)) /* eliminate blanks */
{ /* While */
line[j] = line[j+n];
j++;
} /* While */
*length_ptr = *length_ptr - n; /* reduce 'line_length' */
sum_n = sum_n + n;
} /* If */
} /* If */
i++;
} /* While */
if (sum_n > 0) /* blank trailing char's. */
for (i = (*length_ptr + 1); i < (*length_ptr + 1 + sum_n); i++)
line[i] = ' ';
} /* Compress_Directives */
extern void extension (char fname[],
char ext[] )
/*---------------------------------------------------------------------------*/
/* */
/* Takes the 'fname' and removes the VMS extension and puts it in 'ext'. */
/* - The EXTension is assumed to be between the last '.' */
/* and first ';' OR the last '.' and the first blank character. */
/* For Example: [jones.dir345]file.EXT;67 */
/* - The filename extension is NOT limited to a three character string. */
/* */
/* Rev A-G 7/87- 3/98 Original Initial Development. */
/* Developer Change '<=' to "<" in WHILE loop to */
/* determine the value of stop. */
/* Converted to ANSI-C and unit tested. */
/* Added check for fname[start]='.' */
/* prior to assignment to 'ext' . */
/* Added prototype function headings. */
/* Added null termination of 'ext'. */
/* Added decrement of 'stop' to prevent */
/* copying of ';', or blank, or null */
/* terminator char. to 'ext'. */
/* Inserted '>=' to if statement to allow */
/* copying of file extension delimiter, */
/* i.e., when 'stop' equals 'start'. */
/* Place null only at the end of 'ext'. */
/* Removed "-1" from while conditional of */
/* left-to-right search. */
/* */
/* Rev-H 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-I 1/07/01 GEK Eliminate check for blank character in */
/* left-to-right search in support of */
/* legal filenames that contain blanks. */
/* */
/* Rev-J 7/14/03 GEK Modified left-to-right search of fname */
/* to begin at 'start' instead of '0'. */
/* */
/* Rev-K ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Extension */
long int start;
long int stop ;
long int k ;
for (k = 0; k < MAX_FILENAME_LENGTH; k++) /* Clear 'ext' string */
ext[k] = ' ';
/* Search from right to left */
/* through 'fname' until the*/
/* beginning of the file */
start = MAX_FILENAME_LENGTH - 1; /* extension is located */
while ((start >= 0 ) &&
(fname[start] != '.') )
start--;
/* Search from left to right */
/* through 'fname' until the*/
/* end of the file extension*/
stop = start; /* is located */
while ((stop < MAX_FILENAME_LENGTH) &&
(fname[stop] != ';' ) &&
(fname[stop] != '\0' ) )
stop++;
/* Decrement 'stop' so as */
/* not to copy ';' or blank */
stop--; /* or null terminator char. */
if ((stop >= start ) && /* IF extension has located */
(fname[start] == '.') )
{ /* If */
for (k = start; k <= stop; k++)
ext[k - start] = fname[k]; /* Copy the extension */
} /* If */
ext[MAX_FILENAME_LENGTH] = '\0'; /* Insert null character */
} /* Extension */
extern void transfer_file_name (char in_filename[] ,
char out_filename[] )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will transfer the name of the input file to the parameter */
/* 'out_filename'. If the input filename is larger than */
/* MAX_FILENAME_LENGTH, then the rightmost non-blank characters within */
/* 'in_filename' are moved to 'out_filename'. */
/* */
/* Rev A-C 7/94- 5/97 Original Converted to ANSI-C and unit tested. */
/* Developer Added prototype function headings. */
/* Added check for '\0'. */
/* Clear 'out_filename'. */
/* Transfer only required characters. */
/* */
/* Rev D-F 11/15/00 GEK Replaced static with extern. */
/* Test for location of first blank */
/* character removed due to redundancy */
/* with test for the '\0' character. */
/* */
/* Rev-G ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Transfer_File_Name */
long int stop ;
long int i ;
long int j ;
for (i = 0; i <= MAX_FILENAME_LENGTH; i++)
out_filename[i] = ' '; /* Clear 'out_filename' */
i = 0; /* Locate string terminator */
while ((i < MAX_LIST_FILENAME_LENGTH) && /* within 'in_filename'. */
(in_filename[i] != '\0' ) )
i++;
stop = i; /* Assign value to stop */
if (stop < MAX_FILENAME_LENGTH)
{ /* If */
for (j = 0; j < stop; j++)
out_filename[j] = in_filename[j]; /* Transfer all chars. */
out_filename[stop] = '\0'; /* Insert null character */
} /* If */
else
{ /* Else */
stop -= MAX_FILENAME_LENGTH; /* Transfer rightmost chars. */
for (j = 0; j < MAX_FILENAME_LENGTH; j++)
out_filename[j] = in_filename[stop + j];
out_filename[MAX_FILENAME_LENGTH] = '\0'; /* Insert null character */
} /* Else */
} /* Transfer_File_Name */
extern void get_list_file_size (FILE *listfile ,
long int *num_files_ptr )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will count the number of files to be processed as contained */
/* is '*_list.dat'. This process is the equivalent of determining the */
/* number of physical lines contained within '*_list.dat'. */
/* */
/* Rev A-B 9/96- 5/97 Original Coded and unit tested. */
/* Developer Installed second test to enhance the */
/* accuracy of the function. */
/* */
/* Rev C-D 11/15/00 GEK Corrected assignment of returned value */
/* from fgetc from a char to that of an */
/* int value. */
/* Updated all checks for EOF to be */
/* compared to the int value returned */
/* from fgetc vs. the char value. */
/* Replaced static with extern. */
/* */
/* Rev-E 1/07/01 GEK Modified first test to eliminate fscanf*/
/* that caused filenames containing blank*/
/* characters to cause an overcount. */
/* */
/* Rev-F 7/09/01 GEK Modified first test to correctly */
/* count when listfile terminates without*/
/* an EOLN prior to the EOF. */
/* */
/* Rev-G ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Get_List_File_Size */
list_filename_type filename ;
long int num_1 ;
long int num_2 ;
char list_ch ;
long int list_int ;
*num_files_ptr = 0; /* Initialize */
num_1 = 0; /* 1st test. */
while (fgets(filename, MAX_LIST_FILENAME_LENGTH, listfile) != NULL)
num_1++; /* Found EOLN, or has read a */
/* filename that terminates */
/* with an EOF character, */
/* update num_1. */
rewind(listfile); /* Reset listfile pointer. */
/* 2nd test, susceptible to */
/* undercount when last */
/* filename terminates with */
num_2 = 0; /* EOF rather than '\n'. */
list_int = fgetc(listfile);
list_ch = (char)list_int; /* Get 1st char. */
while (list_int != EOF)
{ /* While */
if (list_ch == '\n')
num_2++;
list_int = fgetc(listfile); /* Get next char. */
list_ch = (char)list_int;
} /* While */
/* Always take larger number */
/* to prevent number of */
/* files processed from */
if (num_1 > num_2) /* exceeding 100 percent. */
(*num_files_ptr) = num_1;
else
(*num_files_ptr) = num_2;
rewind(listfile); /* Reset listfile pointer. */
} /* Get_List_File_Size */
extern void error_handler (error_type *error_cond,
char fname[] ,
FILE *outfile )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will output appropriate error message as determined by the */
/* value of 'error_cond'. Error messages will appear on the terminal */
/* screen AND within the '*outfile.dat' file. */
/* */
/* Rev A-G 9/96- 3/98 Original Coded and unit tested. */
/* Developer Added 'TEMPFILE_OPEN' option. */
/* Added TOOL_PREFIX processing. */
/* Added LINE_TRUNC condition. */
/* Renamed NO_EOLN to LINE_SIZE. */
/* Added 'fname' to argument list. */
/* Added LISTFILE_TRUNC condition. */
/* Changed DSI_COUNT to PHY_COUNT. */
/* Added LOG_COUNT, MATH_ERROR. */
/* Added MAX_HEADER_LENGTH, spaces. */
/* */
/* Rev-E 11/15/00 GEK Replaced static with extern. */
/* */
/* */
/* Rev-F 6/07/01 GEK Added LINE_WRAP condition. */
/* */
/* Rev-G 3/04/03 GEK Added INFILE_EMPTY condition. */
/* */
/* Rev-H ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Error_Handler */
long int spaces;
long int i ;
switch (*error_cond)
{ /* Switch */
case OK :
break;
case OUTFILE_OPEN :
printf("ERROR, unable to open %s_outfile.dat file\n", TOOL_PREFIX);
break;
case LISTFILE_OPEN :
printf("ERROR, unable to open %s_list.dat file\n", TOOL_PREFIX);
fprintf(outfile,"ERROR, unable to open %s_list.dat", TOOL_PREFIX);
fprintf(outfile," file\n");
break;
case LISTFILE_READ :
printf("ERROR, unable to read %s_list.dat file\n", TOOL_PREFIX);
fprintf(outfile,"ERROR, unable to read %s_list.dat", TOOL_PREFIX);
fprintf(outfile," file\n");
break;
case LISTFILE_TRUNC:
printf("ERROR, truncated an entry of the");
printf(" %s_list.dat file\n", TOOL_PREFIX);
fprintf(outfile,"ERROR, truncated an entry of the");
fprintf(outfile," %s_list.dat file\n", TOOL_PREFIX);
break;
case ENVFILE_OPEN :
printf("ERROR, unable to open");
printf(" %s_lines_environment.dat", TOOL_PREFIX);
printf(" file, default values used\n");
fprintf(outfile,"ERROR, unable to open");
fprintf(outfile," %s_lines_environment.dat", TOOL_PREFIX);
fprintf(outfile," file, default values used\n");
break;
case ENVFILE_READ :
printf("ERROR, error in reading");
printf(" %s_lines_environment.dat", TOOL_PREFIX);
printf(" file, default value used\n");
fprintf(outfile,"ERROR, error in reading");
fprintf(outfile," %s_lines_environment.dat", TOOL_PREFIX);
fprintf(outfile," file, default value used\n");
break;
case INFILE_OPEN :
printf("ERROR, unable to access file -> %s\n",fname);
fprintf(outfile,"ERROR, unable to access file ->");
spaces = MAX_HEADER_LENGTH - 31; /* 31 = length of message */
for (i = 0; i < spaces; i++)
fprintf(outfile,"%c",BLANK);
fprintf(outfile,"%s\n",fname);
break;
case INFILE_EMPTY:
printf("ERROR, file contains only an EOF marker -> %s\n",fname);
fprintf(outfile,"ERROR, file contains only an EOF marker ->");
spaces = MAX_HEADER_LENGTH - 42; /* 42 = length of message */
for (i = 0; i < spaces; i++)
fprintf(outfile,"%c",BLANK);
fprintf(outfile,"%s\n",fname);
break;
case LINE_TRUNC :
printf("ERROR, truncated a line of '%s'\n",fname);
fprintf(outfile,"ERROR, truncated a line of file ->");
spaces = MAX_HEADER_LENGTH - 34; /* 34 = length of message */
for (i = 0; i < spaces; i++)
fprintf(outfile,"%c",BLANK);
fprintf(outfile,"%s\n",fname);
break;
case LINE_SIZE :
printf("ERROR, EOLN not detected in '%s'\n",fname);
fprintf(outfile,"ERROR, EOLN not detected in file ->");
spaces = MAX_HEADER_LENGTH - 35; /* 35 = length of message */
for (i = 0; i < spaces; i++)
fprintf(outfile,"%c",BLANK);
fprintf(outfile,"%s\n",fname);
break;
case LINE_WRAP :
printf("ERROR, Word Wrap processing error in '%s'\n",fname);
fprintf(outfile,"ERROR, Word Wrap processing error in file ->");
spaces = MAX_HEADER_LENGTH - 44; /* 44 = length of message */
for (i = 0; i < spaces; i++)
fprintf(outfile,"%c",BLANK);
fprintf(outfile,"%s\n",fname);
break;
case TEMPFILE_OPEN :
printf("ERROR, unable to open temp_file.dat\n");
fprintf(outfile,"ERROR, unable to open temp_file.dat\n");
break;
case PHY_COUNT :
printf("ERROR, Physical SLOC counting error in '%s'\n",fname);
fprintf(outfile,"ERROR, Physical SLOC counting error in the");
fprintf(outfile," following file\n");
break;
case LOG_COUNT :
printf("ERROR, Logical SLOC counting error in '%s'\n",fname);
fprintf(outfile,"ERROR, Logical SLOC counting error in the");
fprintf(outfile," following file\n");
break;
case MATH_ERROR:
printf("ERROR, unable to perform calculation\n");
fprintf(outfile,"ERROR, unable to perform calculation\n");
break;
} /* Switch */
*error_cond = OK; /* Reset 'error_cond' */
} /* Error_Handler */
extern void output_intro_msg (FILE *outfile)
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will output the CodeCount introduction message that appears */
/* as the first page of the output file. This message may be suppressed */
/* by editing the environment data file and setting the 'UD_Intro_Msg' */
/* switch to zero. */
/* */
/* Rev A-B 10/97-11/97 Original Created and unit tested. */
/* Developer Updated due to logical SLOC counting. */
/* */
/* Rev-C 11/15/00 GEK Replaced static with extern. */
/* */
/* Rev-D ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Output_Intro_Msg */
fprintf(outfile,"%20c",BLANK); /* 20 = center in 110 columns*/
fprintf(outfile,"( c ) Copyright 1998 - 2006 ");
fprintf(outfile,"University of Southern California, ");
fprintf(outfile,"CodeCount (TM)\n");
fprintf(outfile,"%36c",BLANK); /* 36 = center in 110 columns*/
fprintf(outfile,"SOURCE LINES OF CODE COUNTING PROGRAM\n");
fprintf(outfile,"\n");
fprintf(outfile," The purpose of the CodeCount toolset is to automate");
fprintf(outfile," the collection of source code sizing information");
fprintf(outfile," using one of two\n");
fprintf(outfile,"possible Source Lines of Code (SLOC) definitions, physical");
fprintf(outfile," or logical. The physical SLOC definition is based on");
fprintf(outfile," Dr. Barry\n");
fprintf(outfile,"W. Boehm's Deliverable Source Instruction (DSI), i.e.,");
fprintf(outfile," non-blank, non-comment, physical source-level lines of");
fprintf(outfile," code and was\n");
fprintf(outfile,"selected due to its inherent programming language syntax");
fprintf(outfile," independence. The logical SLOC definition is based on");
fprintf(outfile," logical\n");
fprintf(outfile,"statements and will vary across programming languages due");
fprintf(outfile," to language-specific syntax. To select the output of");
fprintf(outfile," physical\n");
fprintf(outfile,"versus logical SLOC, edit the %s_lines_", TOOL_PREFIX);
fprintf(outfile,"environment.dat file and set the UD_SLOC_Def switch");
fprintf(outfile," accordingly.\n");
fprintf(outfile," The total sizing of analyzed source code files in");
fprintf(outfile," terms of the SLOC count contains the highest degree of");
fprintf(outfile," confidence.\n");
fprintf(outfile,"However, the sizing data pertaining to the subclass");
fprintf(outfile,"ifications (compiler directives, data declarations,");
fprintf(outfile," executable\n");
fprintf(outfile,"instructions) has a somewhat lower level of confidence");
fprintf(outfile," associated with them. Misclassification of the sub");
fprintf(outfile,"classifications\n");
fprintf(outfile,"of SLOC may occur due to (1) user modifications of the");
fprintf(outfile," tool, (2) syntax and semantic enhancements to the parsed");
fprintf(outfile," programming\n");
fprintf(outfile,"language, (3) exotic usage of parsed programming");
fprintf(outfile," language constructs, and (4) integrity of the host");
fprintf(outfile," platform execution\n");
fprintf(outfile,"environment. Additionally, in some programming");
fprintf(outfile," languages a single SLOC may contain attributes of both");
fprintf(outfile," a data declaration\n");
fprintf(outfile,"and an executable instruction simultaneously. These");
fprintf(outfile," occurrences represent events beyond the control of the");
fprintf(outfile," CodeCount tool\n");
fprintf(outfile,"designer and may cause the inclusive parsing capabilities");
fprintf(outfile," of the tool to misclassify a particular SLOC. For");
fprintf(outfile," these reasons,\n");
fprintf(outfile,"the counts of subclassifications should be regarded as");
fprintf(outfile," an approximation and not as a precise count. In all");
fprintf(outfile," cases, the sum\n");
fprintf(outfile,"of the subclassifications should equal the total SLOC");
fprintf(outfile," sizing, else an error message will be output from the");
fprintf(outfile," tool.\n");
fprintf(outfile," Please refer to the instructions within the header");
fprintf(outfile," documentation of the CodeCount tool under BASIC");
fprintf(outfile," ASSUMPTIONS for more\n");
fprintf(outfile,"information pertaining to the operation of this tool.\n");
fprintf(outfile," To suppress the output of this message, edit the");
fprintf(outfile," %s_lines_environment.dat file and set the ", TOOL_PREFIX);
fprintf(outfile,"UD_Intro_Msg switch to zero.\n");
fprintf(outfile," This product is licensed to : %s\n", LICENTIATE);
fprintf(outfile,"\f\n");
} /* Output_Intro_Msg */
extern void get_user_info (char ud_project_name[] ,
long int *ud_qa_switch_ptr ,
long int *ud_compare_spec_ptr,
long int *ud_line_length_ptr ,
long int *ud_exec_lines_ptr ,
long int *ud_data_lines_ptr ,
double *ud_min_percent_ptr ,
double *ud_inc_percent_ptr ,
long int *ud_display_file_ptr,
long int *ud_intro_msg_ptr ,
char *ud_SLOC_def_ptr ,
char *ud_wordwrap_ptr ,
error_type *error_cond ,
FILE *env_file )
/*---------------------------------------------------------------------------*/
/* */
/* Procedure will accept user-defined parameters from the external file */
/* '*_lines_environment.dat'. An error upon reading this file will */
/* cause the default parameters to be assigned and an error message to */
/* be embedded into the project name of the output file header. */
/* */
/* Note UD prefix implies that this is a User-Definable quantity. */
/* */
/* Rev A-J 7/94- 3/98 Original Converted to ANSI-C and unit tested. */
/* Developer Added prototype function headings. */
/* Deleted 'read_error'. */
/* Added 'env_file' and 'error_cond' to */
/* argument list. */
/* Moved fopen and fclose of environment */
/* file to the main procedure. */
/* Local variables declared as long int. */
/* Added 'ud_inc_percent argument. */
/* Added termination of 'ud_project_name'.*/
/* Added 'ud_display_file'. */
/* Renamed 'new_val' to 'chr_val'. */
/* Renamed 'old_val' to 'lch_val'. */
/* Modified code that moves file pointer */
/* to the EOLN. */
/* Added test for EOF. */
/* Added 'ud_intro_msg'. */
/* Deleted 'error_message' string. */
/* Added 'ud_SLOC_def_ptr'. */
/* Changed 'ud_min_percent_ptr' to float. */
/* Changed all floats to double. */
/* Changed all %d and %f to %ld and %lf */
/* where long int and doubles are output.*/
/* Added int cast to convert 'chr_val' to */
/* 'lch_val'. */
/* */
/* Rev K-L 11/15/00 GEK Changed assignment of returned value */
/* from fgetc from a char to that of an */
/* int value. */
/* Updated all checks for EOF to be */
/* compared to the int value returned */
/* from fgetc vs. the char value. */
/* Replaced static with extern. */
/* */
/* Rev-M 6/07/01 GEK Added 'ud_wordwrap_ptr'. */
/* */
/* Rev-N ??/??/?? */
/* */
/*---------------------------------------------------------------------------*/
{ /* Get_User_Info */
#define DEFAULT_QA_SWITCH 0 /* Default values when the */
#define DEFAULT_COMPARE_SPEC 1 /* environment file could */
#define DEFAULT_LINE_LENGTH MAX_LINE_LENGTH /* not be accessed. */
#define DEFAULT_EXEC_LINES 100
#define DEFAULT_DATA_LINES 100
#define DEFAULT_MIN_PERCENT 60.0
#define DEFAULT_INC_PERCENT 5.0
#define DEFAULT_DISPLAY_SPEC 0
#define DEFAULT_INTRO_MSG 1
#define DEFAULT_SLOC_DEF 'L'
#define DEFAULT_WORDWRAP 'N'
long int value ;
double fvalue ;
long int i ;
long int lch_val ;
char chr_val ;
if (*error_cond == ENVFILE_OPEN)
{ /* If error */
for (i = 0; i < MAX_PROJECT_NAME; i++)
ud_project_name[i] = ' ';
ud_project_name[MAX_PROJECT_NAME] = '\0';
*ud_qa_switch_ptr = DEFAULT_QA_SWITCH ;
*ud_compare_spec_ptr = DEFAULT_COMPARE_SPEC;
*ud_line_length_ptr = DEFAULT_LINE_LENGTH ;
*ud_exec_lines_ptr = DEFAULT_EXEC_LINES ;
*ud_data_lines_ptr = DEFAULT_DATA_LINES ;
*ud_min_percent_ptr = DEFAULT_MIN_PERCENT ;
*ud_inc_percent_ptr = DEFAULT_INC_PERCENT ;
*ud_display_file_ptr = DEFAULT_DISPLAY_SPEC;
*ud_intro_msg_ptr = DEFAULT_INTRO_MSG ;
*ud_SLOC_def_ptr = DEFAULT_SLOC_DEF ;
*ud_wordwrap_ptr = DEFAULT_WORDWRAP ;
} /* If error */
else
{ /* Else no error */
/*---------------------------------------------------------------------------*/
/* Get project name. */
/* Project name centered in */
/* MAX_PROJECT_NAME spaces. */
lch_val = fgetc(env_file);
chr_val = (char)lch_val; /* Convert integer to char. */
if (lch_val != EOF)
*error_cond = OK; /* Continue processing */
else
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
if (lch_val != EOF)
{ /* If not EOF */
i = 0;
while ((chr_val != '\n' ) &&
(lch_val != EOF ) &&
(i < MAX_PROJECT_NAME) )
{
ud_project_name[i] = chr_val;
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
i++;
}
ud_project_name[i] = '\0'; /* Terminate string variable.*/
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get QA_SWITCH. */
/* If set to '1', will */
/* activate software to */
/* output statistics on the */
/* use of certain language */
/* specific keywords. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%ld", &value); /* Input value */
if ((value == 0) ||
(value == 1) )
*ud_qa_switch_ptr = value; /* Assign input value */
else
{ /* Assign default value */
*ud_qa_switch_ptr = DEFAULT_QA_SWITCH;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get COMPARE_SPEC. */
/* If set to '1', letters */
/* must compare exactly */
/* during the Search */
/* procedure. If set to */
/* '0', then a valid */
/* comparison will occur */
/* between an upper case */
/* letter and the */
/* corresponding lower case */
/* letter. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%ld", &value); /* Input value */
if ((value == 0) ||
(value == 1) )
*ud_compare_spec_ptr = value; /* Assign input value */
else
{ /* Assign default value */
*ud_compare_spec_ptr = DEFAULT_COMPARE_SPEC;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get LINE_LENGTH. */
/* Length of a source line */
/* to be read from an input */
/* file. */
/* Length = 0 turns on the */
/* wordwrap feature. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%ld", &value); /* Input value */
if ((value >= 1 ) &&
(value <= MAX_LINE_LENGTH) )
{ /* Assign input value */
*ud_line_length_ptr = value;
*ud_wordwrap_ptr = 'N' ; /* Turn off wordwrap feature */
}
else
if (value == 0)
{ /* Assign DEFAULT value */
*ud_line_length_ptr = DEFAULT_LINE_LENGTH;
*ud_wordwrap_ptr = 'W'; /* Turn on wordwrap feature */
}
else
{ /* Assign DEFAULT values */
*ud_line_length_ptr = DEFAULT_LINE_LENGTH;
*ud_wordwrap_ptr = DEFAULT_WORDWRAP;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get EXEC_LINES. */
/* Maximum number of */
/* executable instructions */
/* allowed per input file. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%ld", &value); /* Input value */
if (value > 0)
*ud_exec_lines_ptr = value; /* Assign input value */
else
{ /* Assign default value */
*ud_exec_lines_ptr = DEFAULT_EXEC_LINES;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get DATA_LINES. */
/* Maximum number of data */
/* declarations allowed per */
/* input file. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%ld", &value); /* Input value */
if (value > 0)
*ud_data_lines_ptr = value; /* Assign input value */
else
{ /* Assign default value */
*ud_data_lines_ptr = DEFAULT_DATA_LINES;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get MIN_PERCENT. */
/* Minimum percent ratio of */
/* comments to deliverable */
/* source instructions. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%lf", &fvalue); /* Input value */
if ((fvalue > 0.0) &&
(fvalue < 1000.0) )
*ud_min_percent_ptr = fvalue; /* Assign input value */
else
{ /* Assign default value */
*ud_min_percent_ptr = DEFAULT_MIN_PERCENT;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get INC_PERCENT. */
/* Increment percent used to */
/* report progress through */
/* *_list.dat file. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%lf", &fvalue); /* Input value */
if ((fvalue >= 0.0) &&
(fvalue <= 100.0) )
*ud_inc_percent_ptr = fvalue; /* Assign input value */
else
{ /* Assign default value */
*ud_inc_percent_ptr = DEFAULT_INC_PERCENT;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get DISPLAY_FILE. */
/* If set to '1', the name */
/* of the file within */
/* *_list.dat that is */
/* currently being */
/* processed will be */
/* displayed on the terminal*/
/* screen. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%ld", &value); /* Input value */
if ((value == 0) ||
(value == 1) )
*ud_display_file_ptr = value; /* Assign input value */
else
{ /* Assign default value */
*ud_display_file_ptr = DEFAULT_DISPLAY_SPEC;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get INTRO_MSG. */
/* If set to '0', the output */
/* of the intro. message */
/* will be suppressed. */
if (lch_val != EOF)
{ /* If not EOF */
fscanf(env_file, "%ld", &value); /* Input value */
if ((value == 0) ||
(value == 1) )
*ud_intro_msg_ptr = value; /* Assign input value */
else
{ /* Assign default value */
*ud_intro_msg_ptr = DEFAULT_INTRO_MSG;
*error_cond = ENVFILE_READ;
}
lch_val = fgetc(env_file); /* Move file pointer to EOLN */
chr_val = (char)lch_val;
while ((chr_val != '\n') &&
(lch_val != EOF ) )
{
lch_val = fgetc(env_file);
chr_val = (char)lch_val;
}
if (lch_val == EOF)
*error_cond = ENVFILE_READ; /* EOF detected prematurely */
} /* If not EOF */
/*---------------------------------------------------------------------------*/
/* Get SLOC_DEF. */
/* If set to 'P' will enable */
/* physical lines of code. */
/* If set to 'L' will enable */
/* logical lines of code. */
if (lch_val != EOF)
{ /* If not EOF */
lch_val = fgetc(env_file); /* Input value */
chr_val = (char)lch_val;
switch (chr_val)
{ /* Switch */
case 'P':
case 'p':
*ud_SLOC_def_ptr = 'P'; /* Assign input value */
break;
case 'L':
case 'l':
*ud_SLOC_def_ptr = 'L'; /* Assign input value */
break;
default:
*ud_SLOC_def_ptr = DEFAULT_SLOC_DEF; /* Assign default value */
*error_cond = ENVFILE_READ;
break;
} /* Switch */
} /* If not EOF */
} /* Else no error */
} /* Get_User_Info */
/*---------------------------------------------------------------------------*/
int main()
{
project_name_type UD_Project_Name ; /* User Definable quantities */
long int UD_QA_Switch ;
long int UD_Compare_Spec ;
long int UD_Line_Length ;
long int UD_Exec_Lines ;
long int UD_Data_Lines ;
double UD_Min_Percent ;
double UD_Inc_Percent ;
long int UD_Display_File ;
long int UD_Intro_Msg ;
char UD_SLOC_Def ;
char UD_WordWrap ;
list_filename_type list_filename ;
filename_type filename ;
filename_type ext ;
line_type line ;
long int line_length ;
ww_line_type ww_line ;
long int ww_count ;
char ch ;
long int lch ;
char list_ch ;
long int list_int ;
long int SLOC_mode ; /* PHY..LOG range */
long int file_mode ; /* CODE..DATA range */
file_mode_names_type file_mode_names ;
long int lc1,lc2,lc3,lc_t ; /* local index counters */
bool_type lf_1, lf_2 ; /* local flags */
long int i, j ;
total_type total_lines ;
total_type total_blank_lines ;
total_type total_comment_lines ;
total_type total_e_comm_lines ;
total_type total_directive_lines ;
total_type total_data_lines ;
total_type total_exec_lines ;
total_type total_SLOC_lines ;
total_type total_number_files ;
long int exceed_UD_Exec_Lines ;
long int exceed_UD_Data_Lines ;
long int exceed_UD_Min_Percent ;
target_name_array_type dirr_names ; /* List of keywords to be */
/* searched for. */
target_tag_array_type dirr_tags ; /* List of keywords to be */
/* printed out. */
target_length_array_type dirr_length ; /* Lengths of each of the */
/* keywords. */
target_tally_array_type dirr_tally ; /* Tally of detected */
/* keywords. */
target_tally_array_type local_dirr_tally ; /* Tally of keywords in a */
/* line to be used as an */
/* indicator to classify */
/* the line. */
target_name_array_type data_names ; /* List of keywords to be */
/* searched for. */
target_tag_array_type data_tags ; /* List of keywords to be */
/* printed out. */
target_length_array_type data_length ; /* Lengths of each of the */
/* keywords. */
target_tally_array_type data_tally ; /* Tally of detected */
/* keywords. */
target_tally_array_type local_data_tally ; /* Tally of keywords in a */
/* line to be used as an */
/* indicator to classify */
/* the line. */
target_name_array_type exec_names ; /* List of keywords to be */
/* searched for. */
target_tag_array_type exec_tags ; /* List of keywords to be */
/* printed out. */
target_length_array_type exec_length ; /* Lengths of each of the */
/* keywords. */
target_tally_array_type exec_tally ; /* Tally of detected */
/* keywords. */
long int lines ;
long int blank_lines ;
long int comment_lines ;
long int e_comm_lines ;
tally_type directive_lines ;
tally_type data_lines ;
tally_type exec_lines ;
tally_type SLOC_lines ;
long int temp ;
double ftemp ;
long int spaces ;
bool_type found ;
double next_percent ;
long int files_processed ;
long int num_list_files ;
bool_type blank_flag ;
bool_type comment_flag ;
bool_type comment_start ;
new_boolean_type comment_stop ;
bool_type code_on_left ;
bool_type code_on_right ;
bool_type double_slash_comm ;
long int internal_comment ;
bool_type string_flag ;
bool_type directive_flag ;
bool_type directive_continue ;
bool_type begin_paren_flag ;
bool_type end_paren_flag ;
long int paren_count ;
bool_type data_flag ;
bool_type data_continue ;
bool_type found_brace ;
long int num_FOR_IF_WHILE ;
long int num_terminators ;
bool_type SLOC_end_flag ;
line_mode_type line_mode ;
bool_type source_flag ;
bool_type open_error ;
error_type error_cond ;
bool_type close_match ;
long int line_loc ;
time_t today ;
struct tm *current_time ;
/* Characters that can be */
/* appended to keywords to */
/* make identifiers. */
exclude_type exclude =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
/* Characters that can be */
/* located adjacent to a */
/* keyword. */
/* Do not include underscore,*/
/* statement terminator, or */
/* statement separators. */
special_type special = "[]()+/-*<>=,@&~!^?:%{}";
/*****************************************************************************/
/*****************************************************************************/
/* Initialize program, and */
/* open external files. */
/* Open outfile */
if (NULL != (c_outfile = fopen("c_outfile.dat","w")))
error_cond = OK;
else
{
error_cond = OUTFILE_OPEN;
error_handler(&error_cond, NULL, c_outfile);
exit(EXIT_SUCCESS); /* Halt program */
}
/* Open environment file */
if ((NULL != (c_lines_environment = fopen("c_env.dat","r"))) ||
(NULL != (c_lines_environment =
fopen("c_lines_environment.dat","r"))) )
{
error_cond = OK;
get_user_info( UD_Project_Name, &UD_QA_Switch, &UD_Compare_Spec,
&UD_Line_Length,
&UD_Exec_Lines, &UD_Data_Lines, &UD_Min_Percent,
&UD_Inc_Percent, &UD_Display_File, &UD_Intro_Msg,
&UD_SLOC_Def, &UD_WordWrap,
&error_cond, c_lines_environment);
error_handler(&error_cond, NULL, c_outfile);
fclose(c_lines_environment);
}
else
{ /* Insert default values. */
error_cond = ENVFILE_OPEN;
get_user_info( UD_Project_Name, &UD_QA_Switch, &UD_Compare_Spec,
&UD_Line_Length,
&UD_Exec_Lines, &UD_Data_Lines, &UD_Min_Percent,
&UD_Inc_Percent, &UD_Display_File, &UD_Intro_Msg,
&UD_SLOC_Def, &UD_WordWrap,
&error_cond, NULL);
error_handler(&error_cond, NULL, c_outfile);
}
/* Open list file */
if ((NULL != (c_list = fopen( "c_lst.dat","r"))) ||
(NULL != (c_list = fopen("c_list.dat","r"))) )
{
error_cond = OK;
next_percent = UD_Inc_Percent;
files_processed = 0;
get_list_file_size(c_list, &num_list_files);
if (num_list_files == 0)
{
error_cond = LISTFILE_READ;
error_handler(&error_cond, NULL, c_outfile);
exit(EXIT_SUCCESS); /* Halt program */
}
}
else
{
error_cond = LISTFILE_OPEN;
error_handler(&error_cond, NULL, c_outfile);
exit(EXIT_SUCCESS); /* Halt program */
}
/*****************************************************************************/
/* Initialize variables. */
load_name_and_tag_arrays(dirr_names, dirr_tags, dirr_length,
DIRR_NAME_LIST, MAX_DIRR_TARGETS);
load_name_and_tag_arrays(data_names, data_tags, data_length,
DATA_NAME_LIST, MAX_DATA_TARGETS);
load_name_and_tag_arrays(exec_names, exec_tags, exec_length,
EXEC_NAME_LIST, MAX_EXEC_TARGETS);
clear_tally(dirr_tally, MAX_DIRR_TARGETS);
clear_tally(data_tally, MAX_DATA_TARGETS);
clear_tally(exec_tally, MAX_EXEC_TARGETS);
for (file_mode = CODE; file_mode <= DATA; file_mode++)
for (SLOC_mode = PHY; SLOC_mode <= LOG; SLOC_mode++)
{ /* For */
total_lines[file_mode][SLOC_mode] = 0 ;
total_blank_lines[file_mode][SLOC_mode] = 0 ;
total_comment_lines[file_mode][SLOC_mode] = 0 ;
total_e_comm_lines[file_mode][SLOC_mode] = 0 ;
total_directive_lines[file_mode][SLOC_mode] = 0 ;
total_exec_lines[file_mode][SLOC_mode] = 0 ;
total_data_lines[file_mode][SLOC_mode] = 0 ;
total_SLOC_lines[file_mode][SLOC_mode] = 0 ;
total_number_files[file_mode][SLOC_mode] = 0 ;
} /* For */
exceed_UD_Exec_Lines = 0 ;
exceed_UD_Data_Lines = 0 ;
exceed_UD_Min_Percent = 0 ;
file_mode_names[CODE][0] = 'C';
file_mode_names[CODE][1] = 'O';
file_mode_names[CODE][2] = 'D';
file_mode_names[CODE][3] = 'E';
file_mode_names[CODE][4] = '\0';
file_mode_names[DATA][0] = 'D';
file_mode_names[DATA][1] = 'A';
file_mode_names[DATA][2] = 'T';
file_mode_names[DATA][3] = 'A';
file_mode_names[DATA][4] = '\0';
if (UD_Compare_Spec == 1)
close_match = True ; /* Must compare exactly */
else
close_match = False; /* Could compare loosely */
/*****************************************************************************/
/* Print introduction message*/
if (UD_Intro_Msg != 0)
output_intro_msg(c_outfile);
/*****************************************************************************/
/* Print outfile header */
fprintf(c_outfile,"%28c",BLANK); /* 28 = center in 100 columns*/
fprintf(c_outfile,"C/C++ SOURCE LINES OF CODE COUNTING PROGRAM\n");
fprintf(c_outfile,"%11c",BLANK); /* 11 = center in 100 columns*/
fprintf(c_outfile,"( c ) Copyright 1998 - 2006 ");
fprintf(c_outfile,"University of Southern California, ");
fprintf(c_outfile,"CodeCount (TM)\n");
fprintf(c_outfile,"\n");
fprintf(c_outfile," University of Southern California retains");
fprintf(c_outfile," ownership of this copy of software. It is");
fprintf(c_outfile," licensed to you.\n");
fprintf(c_outfile,"Use, duplication, or sale of this product,");
fprintf(c_outfile," except as described in the CodeCount License");
fprintf(c_outfile," Agreement, is\n");
fprintf(c_outfile,"strictly prohibited. This License and your");
fprintf(c_outfile," right to use the software automatically");
fprintf(c_outfile," terminate if\n");
fprintf(c_outfile,"you fail to comply with any provisions of");
fprintf(c_outfile," the License Agreement. Violators may be");
fprintf(c_outfile," prosecuted.\n");
fprintf(c_outfile,"This product is licensed to : %s\n", LICENTIATE);
fprintf(c_outfile,"\n");
spaces = ((100 - MAX_PROJECT_NAME) / 2); /* 100 = 100 columns */
for (i = 0; i < spaces; i++)
fprintf(c_outfile,"%c",BLANK);
fprintf(c_outfile,"%s\n", UD_Project_Name);
fprintf(c_outfile,"\n");
if (UD_SLOC_Def == 'P')
{
fprintf(c_outfile," Total Blank | Comments | Compiler Data ");
fprintf(c_outfile,"Exec. |Physical| File Module\n");
}
else
{
fprintf(c_outfile," Total Blank | Comments | Compiler Data ");
fprintf(c_outfile,"Exec. |Logical | File Module\n");
}
fprintf(c_outfile," Lines Lines | Whole Embedded | Direct. Decl. ");
fprintf(c_outfile,"Instr. | SLOC | Type Name\n");
spaces = MAX_HEADER_LENGTH + MAX_FILENAME_LENGTH;
for (i = 0; i < spaces; i++)
fprintf(c_outfile,"%c",BAR);
fprintf(c_outfile,"\n");
/*****************************************************************************/
/* Get 'infile' name. */
list_int = fgetc(c_list) ;
list_ch = (char)list_int;
while (list_int != EOF)
{ /* While Not EOF(c_list) */
for (i = 0; i < MAX_LIST_FILENAME_LENGTH; i++)
list_filename[i] = BLANK ; /* Clear 'list_filename' */
i = 0; /* Read c_list entry */
while ((list_ch != '\n') &&
(list_int != EOF ) &&
(i < MAX_LIST_FILENAME_LENGTH) )
{
if (list_ch != CR_CHAR) /* Do not write carriage */
list_filename[i] = list_ch; /* returns; MS DOS files. */
list_int = fgetc(c_list) ;
list_ch = (char)list_int;
i++;
}
list_filename[i] = '\0' ; /* Insert null character */
while ((list_ch != '\n') && /* Position pointer to next */
(list_int != EOF ) ) /* entry in c_list */
{
list_int = fgetc(c_list) ;
list_ch = (char)list_int;
i++;
}
if (i > MAX_LIST_FILENAME_LENGTH)
{ /* Skip file due to filename */
error_cond = LISTFILE_TRUNC; /* error. */
error_handler(&error_cond, NULL, c_outfile);
}
else
if (list_int != EOF)
{ /* Continue with next line */
list_int = fgetc(c_list) ; /* by parsing over newline */
list_ch = (char)list_int; /* character. */
}
/*****************************************************************************/
/* Open 'infile', */
/* process file extension, */
/* initialize parameters */
transfer_file_name(list_filename, filename);
if (NULL != (infile = fopen(list_filename,"rw")))
{ /* If 'infile' is open */
error_cond = OK;
open_error = False;
/* Determine if 'infile' */
/* contains C source code */
extension(filename, ext); /* Get file extension. */
source_flag = False; /* Assume data file type */
search(ext,".C ", 0, 4, False, MAX_FILENAME_LENGTH, &found,
&line_loc, 0);
if (found == True)
source_flag = True;
search(ext,".CC ", 0, 4, False, MAX_FILENAME_LENGTH, &found,
&line_loc, 0);
if (found == True)
source_flag = True;
search(ext,".CPP ", 0, 4, False, MAX_FILENAME_LENGTH, &found,
&line_loc, 0);
if (found == True)
source_flag = True;
search(ext,".H ", 0, 4, False, MAX_FILENAME_LENGTH, &found,
&line_loc, 0);
if (found == True)
source_flag = True;
search(ext,".HH ", 0, 4, False, MAX_FILENAME_LENGTH, &found,
&line_loc, 0);
if (found == True)
source_flag = True;
search(ext,".HPP ", 0, 4, False, MAX_FILENAME_LENGTH, &found,
&line_loc, 0);
if (found == True)
source_flag = True;
if (source_flag == True)
file_mode = CODE; /* 'infile' is a source file */
else
file_mode = DATA; /* 'infile' is a data file */
lines = 0 ; /* Reset for new infile */
blank_lines = 0 ;
comment_lines = 0 ;
e_comm_lines = 0 ;
for (SLOC_mode = PHY; SLOC_mode <= LOG; SLOC_mode++)
{ /* For */
directive_lines[SLOC_mode] = 0 ;
data_lines[SLOC_mode] = 0 ;
exec_lines[SLOC_mode] = 0 ;
SLOC_lines[SLOC_mode] = 0 ;
} /* For */
comment_start = False;
comment_stop = UNDEF;
double_slash_comm = False;
string_flag = False;
directive_continue = False;
begin_paren_flag = False;
end_paren_flag = False;
paren_count = 0 ;
data_flag = False;
data_continue = False;
found_brace = False;
num_FOR_IF_WHILE = 0 ;
num_terminators = 0 ;
SLOC_end_flag = False;
line_mode = ANY ;
} /* If 'infile' is open */
else
{ /* Else */
open_error = True;
error_cond = INFILE_OPEN;
error_handler(&error_cond, filename, c_outfile);
} /* Else */
/*****************************************************************************/
/* Detected C source */
if (open_error == False)
{ /* Get first char of infile */
lch = fgetc(infile);
ch = (char)lch;
if (lch == EOF) /* Process an empty file */
{ /* Rev-8 repair */
error_cond = INFILE_EMPTY;
error_handler(&error_cond, filename, c_outfile);
}
}
while ((open_error == False) && /*Rev-10, changed the order of*/
(lch != EOF ) && /* '&&' to make sure lch is */
(source_flag == True ) ) /* assigned before being used*/
{ /* While Not EOF infile */
/*****************************************************************************/
/* Get a line of 'infile' */
for (i = 0; i < UD_Line_Length + 2; i++)
line[i] = BLANK ; /* Clear 'line' */
i = 0; /* Must insert a blank to */
while ((ch != '\n') && /* aid search for any */
(lch != EOF ) && /* embedded comments. */
( i < UD_Line_Length) )
{ /* While */
i++;
if ((ch == FF_CHAR) || /* Replace form feeds, tabs, */
(ch == TAB_CHAR) || /* and carriage return */
(ch == CR_CHAR) ) /* chars with a blank char. */
line[i] = BLANK ;
else
line[i] = ch ;
lch = fgetc(infile); /* Get next character. */
ch = (char)lch;
} /* While */
line_length = i ; /* Length of 'line' read */
line[i+1] = '\0'; /* Insert null character */
if (UD_WordWrap == 'N')
{ /* If no wordwrap */
while ((ch != '\n') && /* Position ptr to beginning */
(lch != EOF ) && /* of next line in infile. */
( i < MAX_EOLN_TRIES) )
{
lch = fgetc(infile);
ch = (char)lch;
i++;
}
if (i > MAX_LINE_LENGTH)
{ /* Terminate, info on line of*/
open_error = True; /* infile will not fit into */
error_cond = LINE_SIZE; /* size of 'line'. */
error_handler(&error_cond, filename, c_outfile);
fclose(infile); /* No further reads from file*/
lch = EOF; /* Will terminate processing.*/
}
else
if (i > UD_Line_Length)
{ /* Terminate, truncated */
open_error = True; /* trailing info. on line of*/
error_cond = LINE_TRUNC; /* infile */
error_handler(&error_cond, filename, c_outfile);
fclose(infile); /* No further reads from file*/
lch = EOF; /* Will terminate processing.*/
}
} /* If no wordwrap */
else
{ /* Else, process wordwrap */
if ((ch != '\n') &&
(ch != EOF ) &&
(line_length == MAX_LINE_LENGTH))
{ /* If, long line */
for (j = 0; j < MAX_WW_LINE_LENGTH; j++)
ww_line[j] = BLANK ; /* Clear 'ww_line' */
ww_line[MAX_WW_LINE_LENGTH] = '\0'; /* Insert null character. */
/* Place remaining char's on */
j = 0; /* line into a circular */
ww_count = 0; /* buffer. */
while ((ch != '\n') &&
(lch != EOF ) )
{ /* While, fill 'ww_line' */
if ((ch == FF_CHAR) || /* Replace form feeds, tabs, */
(ch == TAB_CHAR) || /* and carriage return */
(ch == CR_CHAR) ) /* chars with a blank char. */
ww_line[j] = BLANK;
else
ww_line[j] = ch ;
ww_count++; /* Count # chars until EOLN. */
if (j == (MAX_WW_LINE_LENGTH - 1)) /* Update circular ptrs. */
j = 0; /* Reset to zero. */
else
j++; /* Increment pointer. */
lch = fgetc(infile); /* Get next character. */
ch = (char)lch;
} /* While, fill 'ww_line' */
if (j <= 0) /* Back up pointer one loc */
j = (MAX_WW_LINE_LENGTH - 1); /* due to reading EOLN char.*/
else
j--;
/* Adjust 'ww_count' to */
if (ww_count > MAX_WW_LINE_LENGTH) /* copy last 'n' chars from */
ww_count = MAX_WW_LINE_LENGTH; /* circular buffer. */
/* Copy n chars from circular*/
/* buffer to last n chars */
for (i = ww_count; i > 0; i--) /* of 'line'. */
{ /* For */
line[MAX_LINE_LENGTH - ww_count + i] = ww_line[j];
if (j == 0) /* Update circular ptrs. */
j = MAX_WW_LINE_LENGTH - 1;
else
j--;
} /* For */
/* Insert blank just prior to*/
/* copied chars in 'line'. */
line[MAX_LINE_LENGTH - ww_count] = BLANK;
/* Set error condition if */
/* wordwrap processing has */
/* concatenated a SLOC that */
/* is not a comment line. */
search(line, "//", 0, 1, close_match, line_length, &found,
&line_loc, 0);
/* End delimter should be */
/* located at end of long */
/* comment line. */
search(line, "*/", 0, 1, close_match, line_length, &lf_1,
&line_loc, (MAX_LINE_LENGTH - MAX_WW_LINE_LENGTH));
search(line, "/*", 0, 1, close_match, line_length, &lf_2,
&line_loc, 0);
if ((found == False) &&
(lf_1 == False) &&
(lf_2 == False) &&
(comment_flag == False) )
{
/* Terminate, wordwrap has */
open_error = True; /* compressed a non-comment */
error_cond = LINE_WRAP; /* SLOC within 'line'. */
error_handler(&error_cond, filename, c_outfile);
fclose(infile); /* No further reads from file*/
lch = EOF; /* Will terminate processing.*/
}
} /* If, long line */
} /* Else, process wordwrap */
if (lch != EOF)
{ /* Continue with next line */
lch = fgetc(infile); /* by parsing over newline */
ch = (char)lch; /* character. */
}
/*****************************************************************************/
/* Check for a blank line */
blank_flag = True;
i = 1;
while ((i <= line_length ) &&
(blank_flag == True) )
{ /* While */
if (line[i] != ' ')
blank_flag = False;
else
i++;
} /* While */
if (blank_flag == True)
blank_lines++;
/*****************************************************************************/
/* Overwrite single character*/
/* literals, escape sequence*/
/* literals, and \" prior */
/* to comment search and */
/* string processing. */
if (blank_flag == False)
{ /* If */
for (i = 1; i <= line_length - 2; i++)
{ /* For */
if (line[i] == QUOTE_CHAR)
{ /* If quote */
if (line[i+3] == QUOTE_CHAR)
{ /* Found escape sequence */
line[ i ] = '$'; /* inside of a single char. */
line[i+1] = '$'; /* literal, e.g. '\r', '\'',*/
line[i+2] = '$'; /* or '\"'. */
line[i+3] = '$';
}
if (line[i+2] == QUOTE_CHAR)
{ /* Found single char. literal*/
line[ i ] = '$'; /* e.g. 'a'. */
line[i+1] = '$';
line[i+2] = '$';
}
} /* If quote */
if (line[i-1] == '\\')
if ((line[i] == QUOTE_CHAR) ||
(line[i] == '\"' ) )
{ /* If \' or \" escape seq. */
line[ i ] = '$';
line[i-1] = '$';
} /* If \' or \" escape seq. */
} /* For */
if (line[line_length - 1] == '\\') /* If, epilog of loop */
if ((line[line_length] == QUOTE_CHAR) ||
(line[line_length] == '"' ) )
{
line[ line_length ] = '$'; /* Found \' or \" escape seq.*/
line[line_length - 1] = '$';
}
} /* If */
/*****************************************************************************/
/* */
/* Comment / String processing: */
/* - scan each physical line for the beginning comment delimiter. */
/* - note when code appears prior to comment delimiter to indicate */
/* the comment is an embedded comment. */
/* - scan for a string delimiter. */
/* - overwrite contents of comments including the delimiters. */
/* - blank contents of embedded comments including the delimiters. */
/* - set 'comment_flag' to true for whole line comments. */
/* */
/* Notes: */
/* - the "//" indicates the start of a C++ comment terminated by the EOLN. */
/* - the slash-asterisk indicates the start of an ANSI-C comment. */
/* - the asterisk-slash indicates the end of an ANSI-C comment. */
/* - slash-asterisk-slash triplet is interpreted as the start of a comment.*/
/* - two or more whole line comments on the same physical line shall count */
/* as a single comment so as not to corrupt the physical line check. */
/* */
/*****************************************************************************/
comment_flag = False;
if (blank_flag == False)
{ /* Comment processing */
code_on_left = False;
code_on_right = False;
double_slash_comm = False;
internal_comment = 0 ;
/* Signifies a comment cont- */
/* inuation on a new line */
/* for rewrite of 'line' */
if ((comment_start == True ) &&
(comment_stop == UNDEF) )
{
line[0] = '+';
}
/*****************************************************************************/
/* Continue with comment */
/* processing. */
for (i = 1; i <= line_length; i++)
{ /* For */
switch (line[i])
{ /* Switch */
case ' ':
break; /* Do nothing */
case '/':
if ((string_flag == False) &&
(comment_start == False) &&
(double_slash_comm == False) )
{ /* If */
if ((line[i+1] == '/') &&
(line[i-1] != '*') ) /* Differentiates a double */
/* slash from an asterisk- */
/* slash slash-asterisk set.*/
{ /* If C++ */
if (code_on_left == True)
{
comment_start = True; /* C++ embedded comment */
/* Change delimiters to */
line[i+1] = '*'; /* clear comment */
line[line_length - 1] = '*';
line[line_length ] = '/';
}
else
{ /* Else */
comment_lines++; /* C++ whole line comment */
comment_flag = True;
double_slash_comm = True;
} /* Else */
} /* If C++ */
else
{ /* Else ANSI-C */
if ((line[i+1] == '*' ) &&
(double_slash_comm == False) )
{
comment_start = True ; /* Found comment start */
if (line[i+2] == '/')
line[i+1] = BLANK ; /* Rev-4 repair */
}
} /* Else ANSI-C */
} /* If */
break;
case '*':
if ((line[i+1] == '/' ) &&
(comment_start == True ) && /* Rev-4 repair */
(double_slash_comm == False) )
comment_stop = YES; /* Found comment stop */
break;
default:
if ((comment_start == False) &&
(double_slash_comm == False) )
{ /* If, not a comment */
if (internal_comment == 0)
code_on_left = True; /* Code prior to comment */
else
code_on_right = True; /* Code following comment */
} /* If, not a comment */
} /* Switch */
/* Delete string contents by */
/* overwrite with '$' to */
/* differentiate from */
/* normal blank lines. */
/* Thus, keywords in strings */
/* are not counted. */
/* Ignore string delimiters */
/* within comments. Rev-8 */
if ((line[i] == '"' ) &&
(comment_start == False) &&
(comment_flag == False) )
{ /* If string */
if (string_flag == False)
string_flag = True ; /* Detected a string start */
else
{
string_flag = False; /* Detected a string stop */
line[i] = '$' ;
}
} /* If string */
if (string_flag == True)
{ /* Don't overwrite if line[i]*/
/* is a continuation char. */
if (line[i] != '\\')
line[i] = '$'; /* Clear contents of string */
}
if ((comment_start == True) &&
(comment_stop == YES ) )
{
internal_comment++; /* Found an embedded comment */
comment_start = False;
comment_stop = UNDEF;
}
} /* For */
/* Comment starts but does */
/* not end on same line. */
if ((comment_start == True ) &&
(comment_stop == UNDEF) )
{ /* If */
if (code_on_left == False)
{ /* If */
comment_lines++; /* Whole line comment */
internal_comment = 0;
comment_flag = True ;
} /* If */
else
{ /* Else */
e_comm_lines = e_comm_lines + 1 + internal_comment;
internal_comment = 0;
/* Ensure a matching set */
/* of comment delimiters */
/* for rewrite of 'line' */
line[line_length - 1] = '*';
line[line_length ] = '/';
} /* Else */
} /* If */
/* Continuation of, or */
/* comment starts and ends */
/* on the same line */
if (internal_comment > 0)
{ /* If > 0 */
if ((code_on_left == False) &&
(code_on_right == False) )
{ /* If */
comment_lines++; /* Whole line comment */
internal_comment = 0;
comment_start = False;
comment_stop = UNDEF;
comment_flag = True ;
} /* If */
else
{ /* Else */
e_comm_lines = e_comm_lines + internal_comment;
internal_comment = 0; /* Embedded comment */
comment_start = False;
comment_stop = UNDEF;
} /* Else */
} /* If > 0 */
} /* Comment processing */
/*****************************************************************************/
/* Eliminate remaining */
/* comments from 'line' */
/* prior to keyword search. */
found = False;
if ((comment_flag == False) &&
(blank_flag == False) )
{ /* If */
/* Comment starts on previous*/
/* line and continues onto */
if (line[0] == '+') /* the current line. */
found = True;
for (i = 1; i <= line_length; i++)
{ /* For */
if ((line[ i ] == '/') &&
(line[i+1] == '*') )
found = True; /* Found a comment start */
if ((line[ i ] == '*') &&
(line[i+1] == '/') )
{ /* Found a comment stop */
found = False;
line[ i ] = ' '; /* Blank comment delimiter */
line[i+1] = ' ';
}
if (found == True)
line[i] = ' '; /* Clear contents of comment */
} /* For */
} /* If */
/*****************************************************************************/
/* */
/* Compiler Directive processing: */
/* - scan for DIRR_PREFIX and eliminate spaces (blanks) prior to */
/* directive keyword. */
/* - use DIRR_NAME_LIST to verify that a directive has been detected. */
/* - declare SLOC to be a directive line accordingly. */
/* - increment physical line count. */
/* - search for a continuation character. */
/* - set directive_continue accordingly. */
/* - increment logical line count accordingly. */
/* */
/* Notes: */
/* - directives can continue via a back-slash or via a comma. */
/* - directive processing precedes special processing due to elimination */
/* of DIRR_PREFIX during special processing. */
/* */
/*****************************************************************************/
if ((blank_flag == False) &&
(comment_flag == False) )
if (directive_continue == False)
{ /* If check for direct. */
/* Reset when previous line */
if (line_mode == DIR) /* was classified as a */
line_mode = ANY ; /* directive line. */
directive_flag = False;
compress_directives(line, DIRR_PREFIX, &line_length, &found);
if (found == True) /* Found a directive symbol */
{ /* If DIRR_PREFIX */
clear_tally(local_dirr_tally, MAX_DIRR_TARGETS);
count_targets(dirr_names, local_dirr_tally, dirr_length,
MAX_DIRR_TARGETS, line, close_match, line_length,
&found, &line_loc, exclude);
lc2 = 0;
for (lc1 = 0; lc1 < MAX_DIRR_TARGETS; lc1++)
lc2 = lc2 + local_dirr_tally[lc1];
if (lc2 > 0)
directive_flag = True ;
else
directive_flag = False;
if (directive_flag == True)
{ /* Found directive */
line_mode = DIR ;
directive_lines[PHY]++; /* Update physical SLOC lines*/
search_for_continuation(line, line_length, &directive_continue);
if (directive_continue == False)
directive_lines[LOG]++; /* Update logical SLOC lines */
if (UD_QA_Switch == 1)
for (lc1 = 0; lc1 < MAX_DIRR_TARGETS; lc1++)
dirr_tally[lc1] = dirr_tally[lc1] + local_dirr_tally[lc1];
} /* Found directive */
} /* If DIRR_PREFIX */
} /* If check for direct. */
else
{ /* Else directive continue */
directive_flag = True ;
directive_lines[PHY]++; /* Update physical SLOC lines*/
count_targets(dirr_names, dirr_tally, dirr_length,
MAX_DIRR_TARGETS, line, close_match, line_length,
&found, &line_loc, exclude);
search_for_continuation(line, line_length, &directive_continue);
if (directive_continue == False)
directive_lines[LOG]++; /* Update logical SLOC lines */
} /* Else directive continue */
/*****************************************************************************/
/* */
/* Special processing: */
/* - determine the number of '}' statement terminators per physical line. */
/* - determine the number of ';' statement terminators per physical line. */
/* - don't count '}' followed immediately by a ';'. */
/* - don't count ';'s inside of parenthesis, e.g. for conditionals. */
/* - increment number of statement terminators due to occurrences of FOR, */
/* IF and WHILE statements that do not terminate with a '}'. */
/* - blank characters from 'line' that are contained in 'special'. */
/* */
/* Notes: */
/* - FOR, IF, and WHILE keywords can be followed by a left paren. */
/* */
/*****************************************************************************/
if ((blank_flag == False) &&
(comment_flag == False) &&
(directive_flag == False) )
{ /* If */
/* Search for IF */
search(line, " if ", 0, 3, close_match, line_length, &lf_1,
&line_loc, 0);
search(line, " if(", 0, 3, close_match, line_length, &lf_2,
&line_loc, 0);
if ((lf_1 == True) ||
(lf_2 == True) )
num_FOR_IF_WHILE++; /* Inc with each occurrence. */
/* Search for FOR */
search(line, " for ", 0, 4, close_match, line_length, &lf_1,
&line_loc, 0);
search(line, " for(", 0, 4, close_match, line_length, &lf_2,
&line_loc, 0);
if ((lf_1 == True) ||
(lf_2 == True) )
num_FOR_IF_WHILE++; /* Inc with each occurrence. */
/* Search for WHILE */
search(line, " while ", 0, 6, close_match, line_length, &lf_1,
&line_loc, 0);
search(line, " while(", 0, 6, close_match, line_length, &lf_2,
&line_loc, 0);
if ((lf_1 == True) ||
(lf_2 == True) )
num_FOR_IF_WHILE++; /* Inc with each occurrence. */
for (i = 1; i <= line_length; i++)
{ /* For */
if (line[i] == '(') /* Used to terminate data */
{ /* declar. in arg. lists. */
begin_paren_flag = True;
paren_count++;
}
if (line[i] == ')') /* Used to terminate data */
{ /* declar. in arg. lists. */
end_paren_flag = True;
paren_count--;
}
if (line[i] == ';') /* Process ';' not within ()s*/
if (paren_count == 0)
{
if (found_brace == False)
{ /* Will not update a logical */
SLOC_end_flag = True; /* SLOC when '}' is followed*/
num_terminators++; /* by a ';'. */
if (num_FOR_IF_WHILE >= 0) /* All previous FOR, IF, or */
{ /* WHILE statements did not */
/* have a ';' or '}' logical*/
/* SLOC terminator. */
exec_lines[LOG] = exec_lines[LOG] + num_FOR_IF_WHILE;
num_FOR_IF_WHILE = 0; /* Reset for next occurrence.*/
}
else
{ /* Error, can't be < 0. */
error_cond = LOG_COUNT;
error_handler(&error_cond, filename, c_outfile);
num_FOR_IF_WHILE = 0;
}
}
}
else
line[i] = ' '; /* Blank ';' in FOR construct*/
if (found_brace == True) /* Continue processing '}' */
{ /* by examining next char. */
if (line[i] == ',')
{
SLOC_end_flag = False; /* Continuation of current */
found_brace = False; /* line, '}' is not a */
num_terminators--; /* logical SLOC terminator. */
}
if (line[i] != ' ')
{ /* '}' is a logical SLOC */
found_brace = False; /* terminator, expect to */
} /* detect more ';'s. */
}
if (line[i] == '}')
{ /* Logical SLOC terminator */
SLOC_end_flag = True;
found_brace = True;
num_terminators++;
}
if ((line[i] == '{') && /* Block for FOR, IF, or */
(num_FOR_IF_WHILE > 0 ) ) /* WHILE will be processed */
num_FOR_IF_WHILE--; /* when '}' is detected. */
if (NULL != strchr(special, line[i]))
line[i] = ' ';
} /* For */
} /* If */
/*****************************************************************************/
/* */
/* Data Line processing: */
/* - use DATA_NAME_LIST to determine that a data line has been detected. */
/* - declare SLOC to be a data line accordingly. */
/* - increment physical line count. */
/* - use previous detection of a terminal ';' or '}' to indicate */
/* termination of the data line. */
/* - increment logical line count accordingly. */
/* */
/* Notes: */
/* - default is an executable line. */
/* */
/*****************************************************************************/
if ((blank_flag == False) &&
(comment_flag == False) &&
(directive_flag == False) )
{ /* If */
/* data_continue is true only*/
/* during processing of */
/* data declarations. */
if ((data_flag == True ) &&
(data_continue == False) )
data_flag = False; /* Reset data_flag */
clear_tally(local_data_tally, MAX_DATA_TARGETS);
count_targets(data_names, local_data_tally, data_length,
MAX_DATA_TARGETS, line, close_match, line_length,
&found, &line_loc, exclude);
lc2 = 0;
for (lc1 = 0; lc1 < MAX_DATA_TARGETS; lc1++)
lc2 = lc2 + local_data_tally[lc1];
if ((lc2 > 0 ) ||
(data_continue == True) )
data_flag = True ;
else
data_flag = False;
if (data_flag == True)
{ /* If data declaration */
line_mode = DAT ;
data_lines[PHY]++; /* Update physical SLOC lines*/
if (SLOC_end_flag == True)
{
/* Update logical SLOC lines */
data_lines[LOG] = data_lines[LOG] + num_terminators;
SLOC_end_flag = False; /* Reset for next SLOC line */
num_terminators = 0 ;
line_mode = ANY ;
data_continue = False;
}
else
data_continue = True ;
if (UD_QA_Switch == 1) /* Look for keywords */
for (lc1 = 0; lc1 < MAX_DATA_TARGETS; lc1++)
data_tally[lc1] = data_tally[lc1] + local_data_tally[lc1];
} /* If data declaration */
} /* If */
/*****************************************************************************/
/* */
/* Executable Line processing: */
/* - default is an executable line. */
/* - declare SLOC to be a executable line accordingly. */
/* - increment physical line count. */
/* - use previous detection of a terminal ';' or '}' to indicate */
/* termination of the data line. */
/* - increment logical line count accordingly. */
/* - count keywords in EXEC_NAME_LIST. */
/* */
/* Notes: */
/* - */
/* */
/*****************************************************************************/
if ((blank_flag == False) &&
(comment_flag == False) &&
(directive_flag == False) &&
(data_flag == False) )
{ /* If */
line_mode = EXE ;
exec_lines[PHY]++; /* Update physical SLOC lines*/
if (SLOC_end_flag == True)
{
/* Update logical SLOC lines */
exec_lines[LOG] = exec_lines[LOG] + num_terminators;
SLOC_end_flag = False; /* Reset for next SLOC line */
num_terminators = 0 ;
line_mode = ANY ;
}
if (UD_QA_Switch == 1) /* Search for keywords. */
count_targets(exec_names, exec_tally, exec_length,
MAX_EXEC_TARGETS, line, close_match, line_length,
&found, &line_loc, exclude);
} /* If */
/*****************************************************************************/
/* Fault Tolerance against */
/* misclassification of */
/* data_lines following end */
/* of a function argument */
/* list. */
if ((begin_paren_flag == True) &&
( end_paren_flag == True) &&
(paren_count == 0 ) )
{
begin_paren_flag = False; /* Reset, found final */
end_paren_flag = False; /* matching set. */
if ((blank_flag == False) &&
(comment_flag == False) &&
(data_flag == True ) &&
(data_continue == True ) )
{ /* Reset BOOLEANS */
comment_start = False;
comment_stop = UNDEF;
directive_continue = False;
data_continue = False;
string_flag = False;
} /* Reset BOOLEANS */
}
/*****************************************************************************/
/* Update total lines */
lines = lines + 1;
/*****************************************************************************/
} /* While Not EOF(infile) */
/*****************************************************************************/
/* Detected a data file */
while ((open_error == False) && /*Rev-10, changed the order of*/
(lch != EOF ) && /* '&&' to make sure lch is */
(source_flag == False) ) /* assigned before being used*/
{ /* While Not EOF infile */
/*****************************************************************************/
/* Get a line of 'infile' */
for (i = 0; i < UD_Line_Length + 2; i++)
line[i] = BLANK ; /* Clear 'line' */
i = 0; /* Must insert a blank to */
while ((ch != '\n') && /* aid search for any */
(lch != EOF ) && /* embedded comments. */
( i < UD_Line_Length) )
{ /* While */
i++;
if ((ch == FF_CHAR) || /* Replace form feeds, tabs, */
(ch == TAB_CHAR) || /* and carriage return */
(ch == CR_CHAR) ) /* chars with a blank char. */
line[i] = BLANK ;
else
line[i] = ch ;
lch = fgetc(infile); /* Get next character. */
ch = (char)lch;
} /* While */
line_length = i ; /* Length of 'line' read */
line[i+1] = '\0'; /* Insert null character */
while ((ch != '\n') && /* Position ptr to beginning */
(lch != EOF ) && /* of next line in infile. */
( i < MAX_EOLN_TRIES) )
{
lch = fgetc(infile);
ch = (char)lch;
i++;
}
if (i > MAX_LINE_LENGTH)
{ /* Terminate, info on line of*/
open_error = True; /* infile will not fit into */
error_cond = LINE_SIZE; /* size of 'line'. */
error_handler(&error_cond, filename, c_outfile);
fclose(infile); /* No further reads from file*/
lch = EOF; /* Will terminate processing.*/
}
else
if (i > UD_Line_Length)
{ /* Terminate, truncated */
open_error = True; /* trailing info. on line of*/
error_cond = LINE_TRUNC; /* infile */
error_handler(&error_cond, filename, c_outfile);
fclose(infile); /* No further reads from file*/
lch = EOF; /* Will terminate processing.*/
}
else
if (lch != EOF)
{ /* Continue with next line */
lch = fgetc(infile); /* by parsing over newline */
ch = (char)lch; /* character. */
}
/*****************************************************************************/
/* Check for a blank line */
blank_flag = True;
i = 1;
while ((i <= line_length ) &&
(blank_flag == True) )
{ /* While */
if (line[i] != ' ')
blank_flag = False;
else
i++;
} /* While */
if (blank_flag == True)
blank_lines++;
else /* Otherwise data line */
{
data_lines[PHY]++; /* Update physical SLOC lines*/
data_lines[LOG]++; /* Update logical SLOC lines*/
}
/*****************************************************************************/
/* Update total lines */
lines = lines + 1;
/*****************************************************************************/
} /* While Not EOF(infile) */
/*****************************************************************************/
/* Update statistics, & */
/* prepare for next infile */
if (open_error == False)
{ /* If open_error = FALSE */
for (SLOC_mode = PHY; SLOC_mode <= LOG; SLOC_mode++)
{ /* For */
SLOC_lines[SLOC_mode] =
directive_lines[SLOC_mode] +
data_lines[SLOC_mode] +
exec_lines[SLOC_mode] ;
total_lines[file_mode][SLOC_mode] =
total_lines[file_mode][SLOC_mode] + lines ;
total_blank_lines[file_mode][SLOC_mode] =
total_blank_lines[file_mode][SLOC_mode] + blank_lines ;
total_comment_lines[file_mode][SLOC_mode] =
total_comment_lines[file_mode][SLOC_mode] + comment_lines;
total_e_comm_lines[file_mode][SLOC_mode] =
total_e_comm_lines[file_mode][SLOC_mode] + e_comm_lines ;
total_directive_lines[file_mode][SLOC_mode] =
total_directive_lines[file_mode][SLOC_mode] +
directive_lines[SLOC_mode] ;
total_data_lines[file_mode][SLOC_mode] =
total_data_lines[file_mode][SLOC_mode] +
data_lines[SLOC_mode] ;
total_exec_lines[file_mode][SLOC_mode] =
total_exec_lines[file_mode][SLOC_mode] +
exec_lines[SLOC_mode] ;
total_SLOC_lines[file_mode][SLOC_mode] =
total_SLOC_lines[file_mode][SLOC_mode] +
SLOC_lines[SLOC_mode] ;
total_number_files[file_mode][SLOC_mode] =
total_number_files[file_mode][SLOC_mode] + 1 ;
} /* For */
if (source_flag == True)
{ /* If source flag */
if (UD_SLOC_Def == 'P')
{ /* If physical SLOC */
if (exec_lines[PHY] > UD_Exec_Lines)
exceed_UD_Exec_Lines++;
if (data_lines[PHY] > UD_Data_Lines)
exceed_UD_Data_Lines++;
if (SLOC_lines[PHY] > 0 )
{ /* If SLOC > 0 */
ftemp = 100.0 * ((float)(comment_lines + e_comm_lines));
ftemp = ftemp / ((float)(SLOC_lines[PHY]));
if (ftemp < UD_Min_Percent)
exceed_UD_Min_Percent++;
} /* If SLOC > 0 */
if ((lines - blank_lines - comment_lines) != SLOC_lines[PHY])
{
error_cond = PHY_COUNT;
error_handler(&error_cond, filename, c_outfile);
}
} /* If physical SLOC */
else
{ /* Else logical SLOC */
if (exec_lines[LOG] > UD_Exec_Lines)
exceed_UD_Exec_Lines++;
if (data_lines[LOG] > UD_Data_Lines)
exceed_UD_Data_Lines++;
if (SLOC_lines[LOG] > 0 )
{ /* If SLOC > 0 */
ftemp = 100.0 * ((float)(comment_lines + e_comm_lines));
ftemp = ftemp / ((float)(SLOC_lines[LOG]));
if (ftemp < UD_Min_Percent)
exceed_UD_Min_Percent++;
} /* If SLOC > 0 */
} /* Else logical SLOC */
} /* If source flag */
/*****************************************************************************/
/* Close infile & */
/* Print info on infile, */
/* utilize 132 columns */
fclose(infile);
fprintf(c_outfile," %5ld", lines);
fprintf(c_outfile," %5ld", blank_lines);
fprintf(c_outfile," |");
fprintf(c_outfile," %5ld", comment_lines);
fprintf(c_outfile," %5ld", e_comm_lines);
fprintf(c_outfile," |");
if (UD_SLOC_Def == 'P')
{ /* Output physical SLOC info.*/
fprintf(c_outfile," %5ld", directive_lines[PHY]);
fprintf(c_outfile," %5ld", data_lines[PHY]);
fprintf(c_outfile," %5ld", exec_lines[PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %5ld", SLOC_lines[PHY]);
}
else
{ /* Output logical SLOC info. */
fprintf(c_outfile," %5ld", directive_lines[LOG]);
fprintf(c_outfile," %5ld", data_lines[LOG]);
fprintf(c_outfile," %5ld", exec_lines[LOG]);
fprintf(c_outfile," |");
fprintf(c_outfile," %5ld", SLOC_lines[LOG]);
}
fprintf(c_outfile," |");
fprintf(c_outfile," %4s", file_mode_names[file_mode]);
fprintf(c_outfile," %s\n", filename);
} /* If open_error = FALSE */
/*****************************************************************************/
/* Output progress message */
if (UD_Display_File == 1)
printf("Completed File : %s\n", filename);
files_processed++; /* Increment number of files */
ftemp = 100.0 * ((float)(files_processed)) / ((float)(num_list_files));
if ((next_percent <= ftemp) &&
(next_percent != 0.0 ) )
{ /* If, output message */
printf("\n");
spaces = 17; /* Tab over 17 spaces. */
for (i = 0; i < spaces; i++)
printf("%c",BLANK);
printf("%3.1lf%% complete ", ftemp);
printf("(%ld-of-%ld files processed)\n",files_processed,num_list_files);
printf("\n");
temp = ((int)(ftemp/UD_Inc_Percent)) + 1;
next_percent = ((float)(temp)) * UD_Inc_Percent;
} /* If, output message */
/*****************************************************************************/
} /* While Not EOF(c_list) */
/*****************************************************************************/
/* Print outfile trailer */
fprintf(c_outfile,"\f\n");
fprintf(c_outfile,"%28c",BLANK); /* 28 = center in 100 columns*/
fprintf(c_outfile,"C/C++ SOURCE LINES OF CODE COUNTING PROGRAM\n");
fprintf(c_outfile,"%11c",BLANK); /* 11 = center in 100 columns*/
fprintf(c_outfile,"( c ) Copyright 1998 - 2006 ");
fprintf(c_outfile,"University of Southern California, ");
fprintf(c_outfile,"CodeCount (TM)\n");
fprintf(c_outfile,"\n");
fprintf(c_outfile," University of Southern California retains");
fprintf(c_outfile," ownership of this copy of software. It is");
fprintf(c_outfile," licensed to you.\n");
fprintf(c_outfile,"Use, duplication, or sale of this product,");
fprintf(c_outfile," except as described in the CodeCount License");
fprintf(c_outfile," Agreement, is\n");
fprintf(c_outfile,"strictly prohibited. This License and your");
fprintf(c_outfile," right to use the software automatically");
fprintf(c_outfile," terminate if\n");
fprintf(c_outfile,"you fail to comply with any provisions of");
fprintf(c_outfile," the License Agreement. Violators may be");
fprintf(c_outfile," prosecuted.\n");
fprintf(c_outfile,"This product is licensed to : %s\n", LICENTIATE);
fprintf(c_outfile,"\n");
spaces = ((100 - MAX_PROJECT_NAME) / 2); /* 100 = 100 columns */
for (i = 0; i < spaces; i++)
fprintf(c_outfile,"%c",BLANK);
fprintf(c_outfile,"%s\n", UD_Project_Name);
fprintf(c_outfile,"The Totals\n");
fprintf(c_outfile," Total Blank | Comments | Compiler ");
fprintf(c_outfile,"Data Exec. | Number | File SLOC\n");
fprintf(c_outfile," Lines Lines | Whole Embedded | Direct. ");
fprintf(c_outfile,"Decl. Instr. | of Files | SLOC Type ");
fprintf(c_outfile," Definition\n");
spaces = MAX_HEADER_LENGTH + MAX_FILENAME_LENGTH;
for (i = 0; i < spaces; i++)
fprintf(c_outfile,"%c",BAR);
fprintf(c_outfile,"\n");
/* Output physical SLOC info.*/
fprintf(c_outfile," %7ld", total_lines[CODE][PHY]);
fprintf(c_outfile," %7ld", total_blank_lines[CODE][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_comment_lines[CODE][PHY]);
fprintf(c_outfile," %7ld", total_e_comm_lines[CODE][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_directive_lines[CODE][PHY]);
fprintf(c_outfile," %7ld", total_data_lines[CODE][PHY]);
fprintf(c_outfile," %7ld", total_exec_lines[CODE][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %5ld", total_number_files[CODE][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_SLOC_lines[CODE][PHY]);
fprintf(c_outfile," CODE Physical\n");
/* Output logical SLOC info. */
fprintf(c_outfile," %7ld", total_lines[CODE][LOG]);
fprintf(c_outfile," %7ld", total_blank_lines[CODE][LOG]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_comment_lines[CODE][LOG]);
fprintf(c_outfile," %7ld", total_e_comm_lines[CODE][LOG]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_directive_lines[CODE][LOG]);
fprintf(c_outfile," %7ld", total_data_lines[CODE][LOG]);
fprintf(c_outfile," %7ld", total_exec_lines[CODE][LOG]);
fprintf(c_outfile," |");
fprintf(c_outfile," %5ld", total_number_files[CODE][LOG]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_SLOC_lines[CODE][LOG]);
fprintf(c_outfile," CODE Logical\n");
/* Output Data file info. */
fprintf(c_outfile," %7ld", total_lines[DATA][PHY]);
fprintf(c_outfile," %7ld", total_blank_lines[DATA][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_comment_lines[DATA][PHY]);
fprintf(c_outfile," %7ld", total_e_comm_lines[DATA][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_directive_lines[DATA][PHY]);
fprintf(c_outfile," %7ld", total_data_lines[DATA][PHY]);
fprintf(c_outfile," %7ld", total_exec_lines[DATA][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %5ld", total_number_files[DATA][PHY]);
fprintf(c_outfile," |");
fprintf(c_outfile," %7ld", total_SLOC_lines[DATA][PHY]);
fprintf(c_outfile," DATA Physical\n");
if (UD_SLOC_Def == 'P')
temp = total_number_files[CODE][PHY] + total_number_files[DATA][PHY];
else
temp = total_number_files[CODE][LOG] + total_number_files[DATA][LOG];
fprintf(c_outfile,"\n");
fprintf(c_outfile,"Number of files successfully accessed..........");
fprintf(c_outfile,".............. %5ld out of", temp);
fprintf(c_outfile," %ld\n\n", num_list_files);
if (total_SLOC_lines[CODE][LOG] > 0)
{
ftemp = ((float)(total_SLOC_lines[CODE][PHY]));
ftemp = ftemp / ((float)(total_SLOC_lines[CODE][LOG]));
fprintf(c_outfile,"Ratio of Physical to Logical SLOC............");
fprintf(c_outfile,"................ %8.2lf\n", ftemp);
}
else
if (total_number_files[CODE][LOG] > 0)
{
error_cond = MATH_ERROR;
error_handler(&error_cond, filename, c_outfile);
}
fprintf(c_outfile,"\n");
fprintf(c_outfile,"Number of files with :\n");
fprintf(c_outfile," Executable Instructions > ");
fprintf(c_outfile,"%7ld = ", UD_Exec_Lines);
fprintf(c_outfile,"%7ld\n", exceed_UD_Exec_Lines);
fprintf(c_outfile," Data Declarations > ");
fprintf(c_outfile,"%7ld = ", UD_Data_Lines);
fprintf(c_outfile,"%7ld\n", exceed_UD_Data_Lines);
fprintf(c_outfile," Percentage of Comments to SLOC < ");
fprintf(c_outfile," %7.1lf %% = ", UD_Min_Percent);
fprintf(c_outfile,"%7ld", exceed_UD_Min_Percent);
if (UD_SLOC_Def == 'P')
{ /* If, physical */
fprintf(c_outfile,"%6c", BLANK);
if (total_SLOC_lines[CODE][PHY] > 0)
{
ftemp = ((float)(total_comment_lines[CODE][PHY] +
total_e_comm_lines[CODE][PHY] ));
ftemp = 100.0 * ftemp / ((float)(total_SLOC_lines[CODE][PHY]));
fprintf(c_outfile,"Ave. Percentage of Comments to Physical SLOC = ");
fprintf(c_outfile," %3.1lf\n", ftemp);
}
else
{
error_cond = MATH_ERROR;
error_handler(&error_cond, NULL, c_outfile);
}
} /* If, physical */
else
{ /* Else, logical */
fprintf(c_outfile,"%6c", BLANK);
if (total_SLOC_lines[CODE][LOG] > 0)
{
ftemp = ((float)(total_comment_lines[CODE][LOG] +
total_e_comm_lines[CODE][LOG] ));
ftemp = 100.0 * ftemp / ((float)(total_SLOC_lines[CODE][LOG]));
fprintf(c_outfile,"Ave. Percentage of Comments to Logical SLOC = ");
fprintf(c_outfile," %3.1lf\n", ftemp);
}
else
{
error_cond = MATH_ERROR;
error_handler(&error_cond, NULL, c_outfile);
}
} /* Else, logical */
/*****************************************************************************/
if (UD_QA_Switch == 1)
{ /* If UD_QA_Switch */
fprintf(c_outfile,"\n");
fprintf(c_outfile,
"Total occurrences of these C/C++ Keywords :\n");
fprintf(c_outfile,"%3cCompiler Directives", BLANK);
fprintf(c_outfile,"%16cData Keywords", BLANK );
fprintf(c_outfile,"%22cExecutable Keywords\n", BLANK);
lc1 = 0;
lc2 = 0;
lc3 = 0;
lc_t = 0;
lf_1 = True;
while ((lc_t < MAX_TARGETS) &&
(lf_1 == True ) )
{ /* While */
while ((lc1 < MAX_DIRR_TARGETS ) && /* Output Directive keywords */
(dirr_tags[lc1] == False) )
lc1++;
if (lc1 < MAX_DIRR_TARGETS)
{ /* If */
write_dots(dirr_names[lc1], c_outfile);
fprintf(c_outfile,"%7ld%8c", dirr_tally[lc1], BLANK);
lc1++;
} /* If */
else
for (i = 0; i < (MAX_TARGET_LENGTH + 7 + 8); i++)
fprintf(c_outfile, "%c", BLANK);
while ((lc2 < MAX_DATA_TARGETS ) && /* Output Data keywords */
(data_tags[lc2] == False) )
lc2++;
if (lc2 < MAX_DATA_TARGETS)
{ /* If */
write_dots(data_names[lc2], c_outfile);
fprintf(c_outfile,"%7ld%8c", data_tally[lc2], BLANK);
lc2++;
} /* If */
else
for (i = 0; i < (MAX_TARGET_LENGTH + 7 + 8); i++)
fprintf(c_outfile, "%c", BLANK);
while ((lc3 < MAX_EXEC_TARGETS ) && /* Output Exec. keywords. */
(exec_tags[lc3] == False) )
lc3++;
if (lc3 < MAX_EXEC_TARGETS)
{ /* If */
write_dots(exec_names[lc3], c_outfile);
fprintf(c_outfile,"%7ld", exec_tally[lc3]);
lc3++;
} /* If */
fprintf(c_outfile,"\n");
if ((lc1 < MAX_DIRR_TARGETS) || /* Are there still keywords */
(lc2 < MAX_DATA_TARGETS) || /* to print out? */
(lc3 < MAX_EXEC_TARGETS) )
lf_1 = True ;
else
lf_1 = False;
lc_t++; /* Increment row count */
} /* While */
} /* If UD_QA_Switch */
today = time(&today) ;
current_time = localtime(&today);
fprintf(c_outfile,"\n");
fprintf(c_outfile,"REVISION ");
fprintf(c_outfile,"%c",USER_REVISION );
fprintf(c_outfile,"%c",TARGET_REVISION );
fprintf(c_outfile,"%s",DEVELOPER_REVISION);
fprintf(c_outfile," SOURCE PROGRAM -> C_LINES");
fprintf(c_outfile,"%10c", BLANK);
fprintf(c_outfile,"This output produced on %s", asctime(current_time));
fclose(c_outfile);
return EXIT_SUCCESS;
/*****************************************************************************/
} /* C_LINES */