From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.5-pre1 (2020-06-20) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.5-pre1 Date: 28 Sep 92 02:00:48 GMT From: emery@mitre-bedford.arpa (David Emery) Subject: Re: How are SLOC defined in Ada? Message-ID: List-Id: -- Here is the public domain 'statement counter', originally coded by -- Bill Whitaker in the dark ages. I've made some modifications (some -- of which may not work... :-), but the basic algorithm is unchanged. -- dave package Lines_Of_Code is type Lines is record AS : Natural; -- Ada statements Cmnts : Natural; -- Comments -- emery hack Lfs : Natural; -- lines (newlines) -- end of hack end record; function LOC (FILE_NAME : STRING) return Lines; --| Description --| This function calculates the Ada statements and comments of a valid --| Ada fragment specified by a FILE_NAME string parameter. --| It need not be a complete compilation unit but it must have closed --| all open parentheses and string delimiters. --| The Ada statement is defined by a semicolon terminator --| outside of comments, parentheses, or string or character literals --| This definition is insensitive to formatting or layout of the source --| William A. Whitaker WIS JPMO 3 March 1984 --| Modified rh 17 May 1986 --| emery 18 MAR 87 end Lines_Of_Code; with text_io; package natural_IO is new text_io.integer_io (natural); with Lines_Of_Code; use Lines_Of_Code; with Command_Line; use Command_Line; with Text_IO; use Text_IO; with Natural_IO; use Natural_IO; procedure Count_Ada_Statements is stmts_posn : Text_IO.positive_count := 35; cmts_posn : Text_IO.positive_count := 50; ls_posn : Text_IO.positive_count := 65; line_len : positive := 79; dashes : string(1..line_len) := (others => '_'); Usage : constant String := "Usage: cas file1 .. filen "; type str_ptr is access string; totals : Lines_Of_Code.lines := (0,0,0); this_file : str_ptr; this_count : Lines_Of_Code.lines; procedure print_entry (s : string; l : Lines_of_Code.lines); procedure print_header; procedure print_entry (s : string; l : Lines_of_Code.lines) is separate; procedure print_header is separate; begin if argc <= 1 then Put_line (Usage); else print_header; for I in 1..argc - 1 loop if (i mod 52 = 0) then print_header; Text_IO.new_page; end if; this_file := new string'(argv.all(i).all.s); this_count := loc (this_file.all); totals.AS := totals.AS + this_count.AS; totals.Cmnts := totals.Cmnts + this_count.Cmnts; totals.Lfs := totals.Lfs + this_count.Lfs; print_entry (s => this_file.all, l => this_count); end loop; Text_IO.put_line (dashes); Text_IO.new_line; print_entry (s => "***TOTALS***", l => totals); end if; end Count_Ada_Statements; with Text_IO; package body Lines_Of_Code is use Text_IO; function Loc (File_Name : String) return Lines is Input : File_Type; C : Character := ' '; Line_Count : Natural := 0; Comment_Count : Natural := 0; Level : Natural := 0; -- hack New_Lines : Natural := 0; -- end of hack begin Open (Input, In_File, File_Name); loop Get (Input, C); -- Check for comment on the line if C = '-' then Get (Input, C); -- Which is signaled by the '-' following a '-' if C = '-' then Comment_Count := Comment_Count + 1; -- and then just skip the rest of the line and go to the next Skip_Line (Input); end if; end if; -- Check for one of the characters which introduce code constructs -- like string or character literal or formal parameter list -- within which a ';' does not terminate a statement if C = '(' or C = '"' or C = '%' or C = ''' then -- Check for opening parentheses -- Every ';' within is in a formal parameter list if C = '(' then -- Count the number of levels of parentheses Level := Level + 1; -- Read ahead until the whole construct is closed, LEVEL = 0 while Level > 0 loop Get (Input, C); if C = '(' then -- Increase the level if another '(' is found Level := Level + 1; elsif C = ')' then -- Decrease the level if a ')' is found Level := Level - 1; end if; end loop; -- Now check for string brackets of either kind, " or % elsif C = '"' or C = '%' then -- Treat them in parallel, one must lead off if C = '"' then loop Get (Input, C); -- Loop until the close comes -- If there is a doubled character it just starts again exit when C = '"'; end loop; -- The '%' is handled exactly the same way as '"' elsif C = '%' then loop get (Input, C); exit when C = '%'; end loop; end if; -- Character literals are just three characters long including ' elsif C = ''' then Get (Input, C); Get (Input, C); end if; -- Any ';' that can be found at this point after all exclusions -- must be a valid "line of code" terminator elsif C = ';' then Line_Count := Line_Count + 1; end if; end loop; exception -- Return through exception since the end of file may be encountered -- at several levels in the function and in any case it stops and returns -- Otherwise one would use END_OF_FILE but here it would have to appear -- in a number of places to no advantage -- and would cause multiple exits or returns -- This is much cleaner when End_Error => --hacked new_lines := integer(Text_IO.line (Input)); Text_IO.close (Input); return (Line_Count, Comment_Count, new_lines ); -- end of hacking end Loc; -- There has been a certain amount of discussion of how to quantify the -- number of lines of code in an ada program indeed this is a subject of some -- discussion for most languages as ada becomes the dod standard for -- implementations the question takes on more than a philosophical importance -- whether you like it or not there are lots of pieces of paper generated in -- which "lines of code" are quoted some of these are contracts and formal -- costing estimates and can not easily be dismissed nor should there be any -- ambiguity about their meaning money, at least, rides on the definition -- there have been a number of stabs at this definition and i have faced -- estimates within the past couple of weeks based on: -- the number of physical lines (measured by counting ascii.cr) -- the number of physical lines that are not comments or blank -- the number of semicolons -- the number of lines containing at least one semicolon -- as a physicist i have a difficulty accepting measurements that will change -- depending on formatting of the program or introduction of strings or -- comments that do not change the execution therefore i would like to propose -- a modification of the suggested methods that i believe is invarient, at -- least to pretyprinting -- the lines of code would be measured by counting the semicolon statement -- terminators, after excluding: -- -- comments -- separators in formal parameter lists (by excluding parenthesized items) -- string literals (set off by " or %) -- character literals (i.e. ';') -- i think this covers matters and makes a consistant and useful definition -- as useful as any such quantification can be -- i would very much like comments on this matter if i have fouled up let me -- know right away or you may find this in a contract and your paycheck may -- someday depend on it -- in order to assure an unambiguous operational definition i am attaching a -- ada function that describes the measure i believe that this does the -- job without oversimplification or excessive complication -- BILL WHITAKER end Lines_Of_Code; separate (Count_Ada_Statements) procedure print_entry (s : string; l : Lines_of_Code.lines) is next_col : positive; begin Text_IO.put (s); next_col := s'length + 1; Text_IO.set_col (stmts_posn); natural_IO.put (l.AS); Text_IO.set_col (cmts_posn); natural_IO.put (l.Cmnts); Text_IO.set_col (ls_posn); natural_IO.put (l.Lfs); Text_IO.new_line; end print_entry; separate (Count_Ada_Statements) procedure print_header is begin text_io.put ("file name"); Text_IO.set_col (stmts_posn + 2); Text_IO.put ("Ada Stmts"); Text_IO.set_col (cmts_posn + 2); text_io.put ("Comments"); Text_IO.set_col (ls_posn + 1); text_io.put ("line feeds"); Text_IO.new_line; text_IO.put_line (dashes); end print_header;