home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / style / style2.src < prev    next >
Encoding:
Text File  |  1988-05-03  |  398.6 KB  |  10,050 lines

  1. ::::::::::
  2. style_src.dis
  3. ::::::::::
  4. @STYLE_CMP.DIS
  5. -- Help information
  6. style_help.ini
  7. ::::::::::
  8. STYLE_CMP.DIS
  9. ::::::::::
  10. --
  11. --    Compilation order for STYLE_CHECKER
  12. --
  13. -- The names of the following files were changed in order to support
  14. -- 9 significant characters (where one of the 9 is unique):
  15. --    Old Name            New Name
  16. --    REPORT_GEN_BODY.ADA        REPGEN_BODY.ADA
  17. --    REPORT_GEN_SPEC.ADA        REPGEN_SPEC.ADA
  18. --    SEARCH_BACKWARD.ADA        SRCH_BACKWARD.ADA
  19. --    SEARCH_BACK_ONE_OF.ADA        SRCH_BACK_ONE_OF.ADA
  20. --    SEARCH_FORWARD.ADA        SRCH_FORWARD.ADA
  21. --    SEARCH_FORE_ONE_OF.ADA        SRCH_FORE_ONE_OF.ADA
  22. --    STYLE_PARAM_BODY.ADA        SPARAM_BODY.ADA
  23. --    STYLE_PARAM_SPEC.ADA        SPARAM_SPEC.ADA
  24. --    TOKENIZER_BODY.ADA        TOKENZ_BODY.ADA
  25. --    TOKENIZER_SPEC.ADA        TOKENZ_SPEC.ADA
  26. --
  27. --    DYN (dynamic string) package (specification and body)
  28. dyn.ada
  29. --    CURRENT_EXCEPTION - this replaces the Data General package
  30. current_exception.ada
  31. --    FILE_HANDLING package specification
  32. file_spec.ada
  33. --    TOKENIZER package specification
  34. tokenz_spec.ada
  35. --    STYLE_PARAMETERS package specification
  36. sparam_spec.ada
  37. --    REPORT_GENERATOR package specification
  38. repgen_spec.ada
  39. --    STACK_PACKAGE package (specification and body)
  40. stack_package.ada
  41. --    two packages from spelling checker
  42. --       TOKEN_DEFINITION package (specification and body)
  43. token_definition.ada
  44. --       MANAGER package (specification and body)
  45. manager.ada
  46. --    HELP package specification
  47. help_file_spec.ada
  48. --    COMMAND_LINE_HANDLER package (specification and body)
  49. command_line.ada
  50. --    HELP_UTILITY packages
  51. HELPINFO_SPEC.ADA
  52. HELPINFO_BODY.ADA
  53. HELP_SPEC.ADA
  54. HELP_BODY.ADA
  55. HELP_DIS_ALL.ADA
  56. HELP_EXIT.ADA
  57. HELP_FIND.ADA
  58. HELP_GET.ADA
  59. HELP_INIT.ADA
  60. HELP_ME.ADA
  61. HELP_MENU.ADA
  62. HELP_PROMPT.ADA
  63. HELP_RESET.ADA
  64. HELP_TEXT.ADA
  65. --
  66. --
  67. -- And now the bodies...
  68. --
  69. --    HELP package body
  70. help_file_body.ada
  71. --    FILE_HANDLING package body
  72. file_body.ada
  73. --    TOKENIZER package body and all its seperate files
  74. tokenz_body.ada
  75. insert.ada
  76. is_a_reserved_word.ada
  77. reserved_word.ada
  78. next_character.ada
  79. next_identifier.ada
  80. build_tokens.ada
  81. line_containing.ada
  82. tree_root.ada
  83. --    STYLE_PARAMETERS package body
  84. sparam_body.ada
  85. --    REPORT_GENERATOR package body
  86. repgen_body.ada
  87. --    Main procedure (STYLE_CHECKER) and all its seperate files
  88. style_checker.ada
  89. begin_of_line_indent.ada
  90. check_statements.ada
  91. check_end_of_blocks.ada
  92. check_the_style.ada
  93. check_for_attribute.ada
  94. check_object_names.ada
  95. check_universal.ada
  96. comment_token.ada
  97. current_token.ada
  98. entering_block.ada
  99. entering_sub_block.ada
  100. exiting_block.ada
  101. get_next_token.ada
  102. is_statement.ada
  103. literal.ada
  104. new_line_token.ada
  105. non_trivial_token.ada
  106. object_name.ada
  107. reserve_word.ada
  108. srch_backward.ada
  109. srch_back_one_of.ada
  110. srch_forward.ada
  111. srch_fore_one_of.ada
  112. type_declaration.ada
  113. ::::::::::
  114. dyn.ada
  115. ::::::::::
  116. with text_io; use text_io;
  117. package DYN is
  118.  
  119. ------------------------------------------------------------------------------
  120. --  This is a package of several string manipulation functions based on     --
  121. -- a built-in dynamic string type DYN_STRING.  It is an adaptation and      --
  122. -- extension of the package proposed by Sylvan Rubin of Ford Aerospace and  --
  123. -- Communications Corporation in the Nov/Dec 1984 issue of the Journal of   --
  124. -- Pascal, Ada and Modula-2.  Some new functions have been added, the       --
  125. -- SUBSTRING function has been modified to permit it to return the right    --
  126. -- part of a string if the third parameter is permitted to default, and     --
  127. -- much of the body code has been rewritten.                                --
  128. ------------------------------------------------------------------------------
  129. -- R.G. Cleaveland 07 December 1984:                                        --
  130. --  Implementation initially with the Telesoft Ada version                  --
  131. -- This required definition of the DYN_STRING type without use of a         --
  132. -- discriminant; an arbitrary maximum string length was chosen.  This       --
  133. -- should be changed when an improved compiler is available.                --
  134. ------------------------------------------------------------------------------
  135. -- Richard Powers 03 January 1985:                                          --
  136. -- changed to be used with a real compiler.                                 --
  137. -- Some of the routines removed by my whim.                                 --
  138. ------------------------------------------------------------------------------
  139. -- Richard Powers 26 January 1985:
  140. -- Added UPPER_CASE function
  141. ------------------------------------------------------------------------------
  142.  
  143. MAX_LENGTH : constant natural := 255;
  144.  
  145. type DYN_STRING is private;
  146.  
  147. STRING_TOO_SHORT: exception;
  148.  
  149. function D_STRING(CHAR: character)  return DYN_STRING;
  150.         -- Creates a one-byte dynamic string of contents CHAR.
  151.  
  152. function D_STRING(STR : string   )  return DYN_STRING;
  153.         -- Creates a dynamic string of contents STR.
  154.  
  155. -- The following four functions convert from dynamic strings to the
  156. -- desired representation:
  157. function CHAR(DSTR: DYN_STRING) return character;
  158. function STR (DSTR: DYN_STRING) return string;
  159. function INT (DSTR: DYN_STRING) return integer;
  160. function FLT (DSTR: DYN_STRING) return float;
  161.  
  162. function LENGTH(DSTR: DYN_STRING) return natural;
  163. function "<" (DS1, DS2: DYN_STRING) return boolean;
  164. function "&" (DS1, DS2: DYN_STRING) return DYN_STRING;
  165.  
  166. function SUBSTRING (DSTR: DYN_STRING;      -- Returns a subpart of this string
  167.                     START  : natural;      -- starting at this position
  168.                     LENGTH : natural := 0) -- and of this length.
  169.                 return DYN_STRING;
  170.                 -- if LENGTH is zero or not specified, the remainder of the
  171.                 -- string is returned (eg the "RIGHT" function).
  172.  
  173. function INDEX (SOURCE_STRING,              --If this string contains
  174.                 PATTERN_STRING: DYN_STRING; --this string starting at or AFTER
  175.                 START_POS: integer)         --this position, the position of
  176.                 return integer;             --such start is returned.
  177.                 -- If the string lengths prohibit the search -1 is returned.
  178.                 -- If no match was found, 0 is returned.
  179.                 -- (This is like the INSTR function of BASIC).
  180.  
  181. function RINDEX (SOURCE_STRING,             --If this string contains
  182.                 PATTERN_STRING: DYN_STRING; --this string starting at or BEFORE
  183.                 START_POS: integer)         --this position, the position of
  184.                 return integer;             --such start is returned.
  185.                 -- If the string lengths prohibit the search -1 is returned.
  186.                 -- If no match was found, 0 is returned.
  187.  
  188. function UPPER_CASE(STRG : in DYN.DYN_STRING) return STRING;
  189.                 -- Return the input string in upper case
  190.  
  191. subtype STRING_SIZE is natural range 0..MAX_LENGTH;
  192. private
  193.  
  194.         type STRING_CONTENTS(SIZE : STRING_SIZE := 0) is
  195.            record
  196.                DATA: string(1..SIZE);
  197.            end record;
  198.  
  199.         type DYN_STRING is access STRING_CONTENTS;
  200.  
  201. end DYN;
  202.  
  203. ----------------------------------------------------------------------------
  204.  
  205. package body DYN is
  206.  
  207. package MY_INTEGER_IO is new INTEGER_IO(INTEGER);
  208.  
  209. package MY_FLOAT_IO is new FLOAT_IO(FLOAT);
  210.  
  211. function "&" (DS1, DS2: DYN_STRING) return DYN_STRING is
  212.         DS3 : DYN_STRING;
  213.     begin
  214.         DS3 := new STRING_CONTENTS(DS1.SIZE+DS2.SIZE);
  215.         DS3.DATA(1..DS3.SIZE):=   DS1.DATA(1..DS1.SIZE)
  216.                                 & DS2.DATA(1..DS2.SIZE);
  217.         return DS3;
  218.     end "&";
  219.  
  220. function D_STRING(CHAR: character)  return DYN_STRING is
  221.         DS : DYN_STRING;
  222.     begin
  223.         DS := new STRING_CONTENTS(SIZE=>1);
  224.         DS.DATA(1) := CHAR;
  225.         return DS;
  226.     end D_STRING;
  227.  
  228. function D_STRING(STR : string   )  return DYN_STRING is
  229.         DS : DYN_STRING;
  230.     begin
  231.         DS := new STRING_CONTENTS(SIZE => STR'length);
  232.         DS.DATA(1..DS.SIZE)  := STR;
  233.         return DS;
  234.     end D_STRING;
  235.  
  236. function CHAR(DSTR: DYN_STRING) return character is
  237.     begin
  238.         return DSTR.DATA(1);
  239.     end CHAR;
  240.  
  241. function STR (DSTR: DYN_STRING) return string is
  242.     begin
  243.         return DSTR.DATA(1..DSTR.SIZE);
  244.     end STR;
  245.  
  246. function INT (DSTR: DYN_STRING) return integer is
  247.         V: integer;
  248.         L: positive;
  249.     begin
  250.         MY_INTEGER_IO.get(STR(DSTR),V,L);
  251.         return V;
  252.     end INT;
  253.  
  254. function FLT (DSTR: DYN_STRING) return float is
  255.         V: float;
  256.         L: positive;
  257.     begin
  258.         MY_FLOAT_IO.get(STR(DSTR),V,L);
  259.         return V;
  260.     end FLT;
  261.  
  262. function LENGTH(DSTR: DYN_STRING) return natural is
  263.     begin
  264.         return DSTR.SIZE;
  265.     end LENGTH;
  266.  
  267. function "<" (DS1, DS2: DYN_STRING) return boolean is
  268.     begin
  269.         if STR(DS1) < STR(DS2)
  270.         then return (TRUE);
  271.         else return (FALSE);
  272.         end if;
  273.     end "<";
  274.  
  275. function SUBSTRING (DSTR: DYN_STRING;
  276.                     START  : natural;
  277.                     LENGTH : natural := 0)
  278.                                            return DYN_STRING is
  279.         DS: DYN_STRING;
  280.         L : natural := LENGTH;
  281.     begin
  282.         if (START < 1) or (START > DSTR.SIZE)
  283.         then raise CONSTRAINT_ERROR;
  284.         else if L = 0
  285.              then L := DSTR.SIZE-START+1;
  286.              end if;
  287.              if DSTR.SIZE < START + L - 1
  288.              then  raise STRING_TOO_SHORT;
  289.              else
  290.                    DS := new STRING_CONTENTS(L);
  291.                    DS.DATA(1..L) := DSTR.DATA(START..START+L-1);
  292.                    return DS;
  293.              end if;
  294.          end if;
  295.     end SUBSTRING;
  296.  
  297. function INDEX(SOURCE_STRING, PATTERN_STRING: DYN_STRING;
  298.                         START_POS: integer) return integer is
  299.         NO_MATCH        : integer := 0;
  300.         NO_FIT          : integer := -1;
  301.     begin
  302.         if SOURCE_STRING.SIZE < PATTERN_STRING.SIZE + START_POS - 1
  303.         or START_POS < 1
  304.         then return NO_FIT;
  305.         end if;
  306.         for I in START_POS..SOURCE_STRING.SIZE-PATTERN_STRING.SIZE+1 loop
  307.             if SOURCE_STRING.DATA(I..I+PATTERN_STRING.SIZE-1)
  308.                = PATTERN_STRING.DATA(1..PATTERN_STRING.SIZE)
  309.             then return I;
  310.             end if;
  311.         end loop;
  312.         return NO_MATCH;
  313.     end INDEX;
  314.  
  315. function RINDEX(SOURCE_STRING, PATTERN_STRING: DYN_STRING;
  316.                         START_POS: integer) return integer is
  317.         NO_MATCH        : integer := 0;
  318.         NO_FIT          : integer := -1;
  319.     begin
  320.         if SOURCE_STRING.SIZE < PATTERN_STRING.SIZE + START_POS - 1
  321.         or START_POS < 1
  322.         then return NO_FIT;
  323.         end if;
  324.         for I in reverse 1..START_POS loop
  325.             if SOURCE_STRING.DATA(I..I+PATTERN_STRING.SIZE-1)
  326.                = PATTERN_STRING.DATA(1..PATTERN_STRING.SIZE)
  327.             then return I;
  328.             end if;
  329.         end loop;
  330.         return NO_MATCH;
  331.     end RINDEX;
  332.  
  333.     function UPPER_CASE(STRG : in DYN.DYN_STRING) return STRING is
  334.         ANSWER : STRING(1..LENGTH(STRG));
  335.     begin
  336.         ANSWER := STR(STRG);
  337.         for I in 1..LENGTH(STRG) loop
  338.             if (ANSWER(I) >= 'a') and (ANSWER(I) <= 'z') then
  339.                 ANSWER(I) := CHARACTER'VAL(CHARACTER'POS(ANSWER(I)) -
  340.                     CHARACTER'POS('a') + CHARACTER'POS('A'));
  341.             end if;
  342.         end loop;
  343.         return ANSWER;
  344. end UPPER_CASE;
  345.  
  346. end DYN;
  347. ::::::::::
  348. current_exception.ada
  349. ::::::::::
  350. package CURRENT_EXCEPTION is
  351.  
  352.   NAME : string(1..21) := "An exception occurred";
  353.  
  354. end CURRENT_EXCEPTION;
  355. ::::::::::
  356. file_spec.ada
  357. ::::::::::
  358. --
  359. -- FILE_HANDLING by Richard Conn, TI Ada Technology Branch
  360. -- 28 Feb 85
  361. --
  362. with TEXT_IO;
  363. package FILE_HANDLING is
  364. --------------------------------------------------------------------------
  365. -- Abstract   : FILE_HANDLING returns FILE_IDs for all files specified
  366. --               as parameters, either directly or indirectly, in the
  367. --               command line.  Any file name prefixed by the special
  368. --               character '@' is an indirect file, which contains the
  369. --               names of other files to check and other indirect files.
  370. --               Indirect files may be nested several levels deep (set by
  371. --               a constant), and the prefix character for indirect files
  372. --               may be changed (also by a constant).
  373. --------------------------------------------------------------------------
  374.  
  375.     HELP_ASKED_FOR         : exception;
  376.  
  377.     HELP_FILE_NAME         : constant STRING := "STYLE_HELP.INI";
  378.     STYLE_DICTIONARY_NAME  : constant STRING :=
  379.         "STYLE_DICTIONARY.INI";
  380.  
  381.     procedure INPUT_FILE_ID (FILE_ID    : in out TEXT_IO.FILE_TYPE;
  382.                              MORE_FILES : out BOOLEAN);
  383. --------------------------------------------------------------------------
  384. -- Abstract   : INPUT_FILE_ID returns the next file id of the next file
  385. --               in the direct or indirect file name list from the
  386. --               command line.
  387. --------------------------------------------------------------------------
  388. -- Parameters : FILE_ID        - ID of next file
  389. --              MORE_FILES     - FALSE if no more files available
  390. --                                (FILE_ID is also invalid at this point)
  391. --------------------------------------------------------------------------
  392.  
  393.  
  394.     procedure OUTPUT_FILE_ID (FLAWS_FILE_ID : in out TEXT_IO.FILE_TYPE;
  395.                               STYLE_FILE_ID : in out TEXT_IO.FILE_TYPE);
  396. --------------------------------------------------------------------------
  397. -- Abstract   : OUTPUT_FILE_ID returns the file IDs of the Flaws and Style
  398. --               files.  The names of these files were built from the first
  399. --               file indicated in the list of file names.
  400. --------------------------------------------------------------------------
  401. -- Parameters : FLAWS_FILE_ID  - ID of Flaws File
  402. --              STYLE_FILE_ID  - ID of Style File
  403. --------------------------------------------------------------------------
  404.  
  405. end FILE_HANDLING;
  406. ::::::::::
  407. tokenz_spec.ada
  408. ::::::::::
  409. with DYN;
  410. with TEXT_IO;
  411. package TOKENIZER is
  412. --------------------------------------------------------------------------
  413. -- Abstract   : This package contains the interfaces to the Tokenizer part
  414. --              of the Style_Checker.  The tokenizer splits the input Ada
  415. --              source into "tokens".
  416. --------------------------------------------------------------------------
  417.     -- I don't think the following 'USE' needs to be here, but I'm desperate.
  418.     use DYN;
  419.  
  420.     type TOKEN is private;
  421.  
  422. -- Ranges
  423.     subtype LINE_NUM_RANGE is NATURAL range 0 .. NATURAL'LAST;
  424.     subtype LINE_INDEX_RANGE is NATURAL range 0 .. 255;
  425. -- Types of tokens
  426.  
  427.     type TOKEN_TYPE is (
  428.         --  First the reserved word tokens, alphabetized by LENGTH
  429.         AT_TOKEN, DO_TOKEN, IF_TOKEN, IN_TOKEN, IS_TOKEN, OF_TOKEN, OR_TOKEN,
  430.         ABS_TOKEN, ALL_TOKEN, AND_TOKEN, END_TOKEN, FOR_TOKEN,  MOD_TOKEN,
  431.         NEW_TOKEN, NOT_TOKEN, OUT_TOKEN, REM_TOKEN, USE_TOKEN, XOR_TOKEN,
  432.         BODY_TOKEN, CASE_TOKEN, ELSE_TOKEN, EXIT_TOKEN, GOTO_TOKEN, LOOP_TOKEN,
  433.         NULL_TOKEN, TASK_TOKEN, THEN_TOKEN, TYPE_TOKEN, WHEN_TOKEN, WITH_TOKEN,
  434.         ABORT_TOKEN, ARRAY_TOKEN, BEGIN_TOKEN, DELAY_TOKEN, DELTA_TOKEN,
  435.         ELSIF_TOKEN, ENTRY_TOKEN, RAISE_TOKEN, RANGE_TOKEN, WHILE_TOKEN,
  436.         ACCEPT_TOKEN, ACCESS_TOKEN, DIGITS_TOKEN, OTHERS_TOKEN, PRAGMA_TOKEN,
  437.         RECORD_TOKEN, RETURN_TOKEN, SELECT_TOKEN,
  438.         DECLARE_TOKEN, GENERIC_TOKEN, LIMITED_TOKEN, PACKAGE_TOKEN,
  439.         PRIVATE_TOKEN, RENAMES_TOKEN, REVERSE_TOKEN, SUBTYPE_TOKEN,
  440.         CONSTANT_TOKEN, FUNCTION_TOKEN, SEPARATE_TOKEN,
  441.         EXCEPTION_TOKEN, PROCEDURE_TOKEN, TERMINATE_TOKEN,
  442.         --  Followed by the other tokens (in no particular order)
  443.         END_OF_LINE,
  444.         END_OF_FILE,
  445.         IDENTIFIER,
  446.         NUMERIC_LITERAL,
  447.         STRING_LITERAL,
  448.         CHARACTER_LITERAL,
  449.         CONCATENATION_OPERATOR,         -- &
  450.         TICK,                           -- '
  451.         RIGHT_PARENTHESIS,              -- (
  452.         LEFT_PARENTHESIS,               -- )
  453.         MULTIPLICATION_OPERATOR,        -- *
  454.         ADDITION_OPERATOR,              -- +
  455.         COMMA,                          -- ,
  456.         SUBTRACTION_OPERATOR,           -- -
  457.         PERIOD,                         -- .
  458.         DIVISION_OPERATOR,              -- /
  459.         COLON,                          -- :
  460.         SEMICOLON,                      -- ;
  461.         LESS_THAN_OPERATOR,             -- <
  462.         EQUAL_OPERATOR,                 -- =
  463.         GREATER_THAN_OPERATOR,          -- >
  464.         VERTICAL_BAR,                   -- |
  465.         COMMENT,                        -- --
  466.         ARROW,                          -- =>
  467.         DOUBLE_DOT,                     -- ..
  468.         EXPONENTIATE_OPERATOR,          -- **
  469.         ASSIGNMENT_OPERATOR,            -- :=
  470.         INEQUAL_OPERATOR,               -- /=
  471.         GREATER_THAN_OR_EQUAL_OPERATOR, -- >=
  472.         LESS_THAN_OR_EQUAL_OPERATOR,    -- <=
  473.         LEFT_LABEL_BRACKET,             -- <<
  474.         RIGHT_LABEL_BRACKET,            -- >>
  475.         BOX,                            -- <>
  476.         ANYTHING_ELSE);
  477.  
  478.   subtype KEYWORDS is TOKEN_TYPE range AT_TOKEN .. TERMINATE_TOKEN;
  479.  
  480. --  Types associated with the IDENTIFIER binary tree
  481.  
  482.     type REFS;                                   -- occurrence of an identifier
  483.  
  484.     type REFPTR is access REFS;                  -- pointers to references
  485.  
  486.     type REFS is                                 --
  487.         record
  488.             STRG : DYN.DYN_STRING;               -- identifier
  489.             NEXT : REFPTR;                       -- chained to other occurrences
  490.         end record;
  491.  
  492.     type IDENTIFIER_NODE;                        -- element of identifier tree
  493.  
  494.     type IDENTIFIER_TREE is access IDENTIFIER_NODE;
  495.                                                  -- binary tree used to sort
  496.     type IDENTIFIER_NODE is                      -- Tokens
  497.         record
  498.             LEFT, RIGHT : IDENTIFIER_TREE;       -- links to other nodes
  499.             REFERENCES : REFPTR;                 -- identifier chain
  500.         end record;
  501.  
  502. --  Externally visible functions and procedures
  503.  
  504.     function EXTERNAL_REPRESENTATION(CURRENT_TOKEN : in TOKEN) return
  505.         DYN.DYN_STRING;
  506.  
  507.     function TREE_ROOT return IDENTIFIER_TREE;
  508.     function FIRST_TOKEN return TOKEN;
  509.     function LENGTH_OF_COMMENT(CURRENT_TOKEN : in TOKEN) return NATURAL;
  510.     function NEXT_TOKEN(CURRENT_TOKEN : in TOKEN) return TOKEN;
  511.     function PREVIOUS_TOKEN(CURRENT_TOKEN : in TOKEN) return TOKEN;
  512.     function TYPE_OF_TOKEN_IS(CURRENT_TOKEN : in TOKEN) return TOKEN_TYPE;
  513.  
  514.     procedure BUILD_TOKENS;
  515.     procedure TOKEN_POSITION(CURRENT_TOKEN : in TOKEN;
  516.                              LINE : out LINE_NUM_RANGE;
  517.                              COLUMN : out LINE_INDEX_RANGE);
  518.     procedure LINE_CONTAINING_TOKEN(CURRENT_TOKEN : in TOKEN;
  519.                                     LINE : out DYN.DYN_STRING);
  520. --  Exceptions exported
  521.  
  522.     END_OF_TOKENS : exception;                   -- End of token signal
  523.  
  524.     INVALID_TOKEN : exception;                   -- Invalid token passed in
  525.  
  526. private
  527. --  Types used for identifier tree
  528.  
  529.     type TOKEN_POINTER is access TOKEN;
  530.  
  531.     type TOKEN_POSITION_RECORD is
  532.         record
  533.             LINE : LINE_NUM_RANGE;
  534.             COLUMN : LINE_INDEX_RANGE;
  535.         end record;
  536.  
  537.     type TOKEN is
  538.         record
  539.             TYPE_OF_TOKEN : TOKEN_TYPE;
  540.             PHYSICAL_REPRESENTATION : DYN.DYN_STRING;
  541.             TOKEN_POSITION : TOKEN_POSITION_RECORD;
  542.             NEXT_TOKEN : TOKEN_POINTER;
  543.             PREVIOUS_TOKEN : TOKEN_POINTER;
  544.         end record;
  545. end TOKENIZER;
  546. ::::::::::
  547. sparam_spec.ada
  548. ::::::::::
  549. ------ CPCI-Level PROLOGUE ------
  550.  
  551. --|CPCI Name    I: Style_Parameters
  552. --|Responsible Manager  : John Mellby
  553. --|CPCI II: Style_Parameters
  554. --|Compliance   I:
  555. --
  556. --|Abstract     I: This package is responsible for inputting the
  557. --                        parameters determining the style from a file,
  558. --                        then making them available to the 'style-checking'
  559. --                        remainder of the system.
  560. --
  561. --|Notes        I:
  562. --
  563. --|Implementation Language : Ada
  564. --|LOC  II:
  565. --|Requirements I:
  566. --|Requirements, Derived: The parameters defining the "Style" will be
  567. --                        read into the program from a file.
  568. --|Requirements, Implied:
  569. --|Technical References :
  570. --
  571. --|Program References
  572.         with DYN;                -- Dynamic String Package
  573.         with Tokenizer;
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588. ---- END CPCI-Level PROLOGUE ----
  589.  
  590.  
  591. --                         Style Checker
  592. --                      P A R A M E T E R S
  593.  
  594. -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  595. package Style_Parameters is
  596.  
  597.    Number_of_Keywords : constant integer
  598.         := 1 + (Tokenizer.Keywords'pos(Tokenizer.Keywords'last))
  599.              - (Tokenizer.Keywords'pos(Tokenizer.Keywords'first));
  600.    subtype Keyword_Range is integer range 0..Number_of_Keywords;
  601.    type Keyword_Options  is (All_Keys, Used, Not_Used, Errors, None);
  602.    type Require_Type     is (Required, Not_Required);
  603.  
  604. -- Word and case parameters
  605.    subtype Word_Lengths       is natural;
  606.  
  607.    type Reserve_Word_Cases is (Reserved_Case_Upper,
  608.                               Reserved_Case_Lower,
  609.                               Reserved_Case_Consistant,
  610.                               Reserved_Case_Any);
  611.  
  612.    type Object_Name_Cases  is (Name_Case_Upper,
  613.                               Name_Case_Lower,
  614.                               Name_Case_First_Capitalized,
  615.                               Name_Case_Consistant,
  616.                               Name_Case_Any);
  617.  
  618.  
  619.    subtype Abbreviation_Aves is Float;
  620.  
  621. -- Physical Layout
  622.    type Loop_Names_Needs is  (Required, Average, not_Required);
  623.  
  624. -- Transportability
  625.    type Character_Set_Types is (Basic, Graphic, Extended);
  626.    type Pragma_Classes   is  (All_Pragmas, System_Dependent, None);
  627. --
  628. -- The following is probably to be located in the package body.
  629. --   type Package_Name_Node;
  630. --   type Package_List     is access Package_Name_node;
  631. --   type Package_Name_Node is
  632. --         record
  633. --           P_Name : DYN.DYN_STRING;
  634. --           Next   : Package_List;
  635. --         end record;
  636.  
  637. -- Statement Use
  638.    type Keyword_Use_Type is  (No_Use, Restricted_Use, Free_Use);
  639.    type Keyword_Use_Descript is record
  640.                              Use_Class : Keyword_Use_Type := Free_Use;
  641.                              Use_Freq  : float := 0.0;
  642.                            end record;
  643.    type Keyword_Uses    is array( Tokenizer.keywords ) of Keyword_Use_descript;
  644.  
  645. -------------------------------------
  646. -- This procedure obtains the 'style
  647. -------------------------------------
  648.   Procedure Set_Style_Parameters;
  649.           -- This sets the parameter variables.
  650.  
  651. --------------------------------------------
  652. -- These return style individual parameters
  653. --------------------------------------------
  654.   function Number_of_Errors_to_Report return natural;
  655.   -- This returns a number telling how many times to list
  656.   -- a error in the "Flaws" output.  I.E. If this returns
  657.   -- "3", then only the first three occurences of each
  658.   -- type of error are listed.
  659.  
  660.   function OUTPUT_KEYWORD_LIST return Keyword_Options;
  661.   -- This function returns a value specifying the output format for
  662.   -- listing the reserved word usage.  It specifys which class of
  663.   -- reserved words to output, all keywords, only those keywords
  664.   -- used or not used, keywords used in violation of style restrictions,
  665.   -- or no keywords output.
  666.  
  667.   function OUTPUT_OPERATOR_LIST return boolean;
  668.   -- This function returns true if the operator list is to be printed
  669.   -- as part of the style report.
  670.  
  671.   function SMALL_PROGRAM_SIZE return natural;
  672.   -- returns size of programs considered 'too small' so limits of
  673.   -- some things may be violated with not penalty.
  674.  
  675.   function Small_Word_Size    return Word_Lengths;
  676.   -- returns size of words considered 'too small' so limits of
  677.   -- some things may be violated with no penalty.
  678.  
  679.   function Small_Structure_Size    return Natural;
  680.   -- returns size (in statements) of structures considered 'too small' so
  681.   -- some constraints may be violated with no penalty.
  682.  
  683.   function Case_of_Reserved_Words return Reserve_Word_Cases;
  684.  
  685.   function Case_of_Object_Names return Object_Name_Cases;
  686.  
  687.   function Average_Name_Size  return Word_Lengths;
  688.   -- The average size of names in the program should be greater than
  689.   -- this minimum.
  690.  
  691.   function Is_Underscore_Required return boolean;
  692.   function Average_Underscore_Size return Word_Lengths;
  693.   -- If underscores are required and the word under inspection is
  694.   -- longer than a "Small_Word", then the parts separated by
  695.   -- underscores should be longer than this minimum.
  696.  
  697.   function Vowel_Frequency return float;
  698.   -- To keep people from abbreviating too much, check the percentage of
  699.   -- vowels to consonants.  If (Vowel / Total-letters) is less than
  700.   -- Vowel_Frequency percent, there is something wrong.
  701.   function SPELLING_REQUIRED return Require_Type;
  702.   -- This function returns 'Required' if the style checker is to
  703.   -- send words to a spelling checker to validate variable names.
  704.  
  705.   function Is_One_Statement_per_line_Required return boolean;
  706.   function Is_Declaration_Indentation_Required return boolean;
  707.   -- Forced to indent properly on object, type declarations?
  708.   function Is_Comment_Indentation_Required return boolean;
  709.   -- Forced to indent the trailing comments after statement on a line?
  710.  
  711.   function Is_Blank_Lines_around_Blocks_Required return boolean;
  712.   -- Should blank lines around blocks, loops, etc. be required?
  713.  
  714. -- We deleted this function
  715. --   function Average_Blank_Lines return float;
  716. --   -- The average # of blank lines should be 'Ave-blank-lines' +- delta
  717. --   -- for readability's sake
  718.  
  719.   function Loop_Name_Required return Loop_Names_Needs;
  720.   -- Are loop-names necessary, should loops of a certain size need names.
  721.  
  722.   procedure Reserved_Word_Info ( Usage : out Keyword_Uses );
  723.  
  724.   function Average_Comment_Size return positive;
  725.   -- To prevent style "tricking" comments must have a minimum average
  726.   -- size;
  727.  
  728.   function Average_Literal_in_Body return float;
  729.   -- Literals should be in the declaration rather then the body, so
  730.   -- the number of literals in the body should be less than "ave-literal"
  731.  
  732.   function Average_Universal_Usage return float;
  733.   -- In general, good use should be made of programmer-defined types
  734.   -- rather than universal integer, float, etc.  The percentage of
  735.   -- types which are universal integer, float, natural, positive, etc.
  736.   -- should be less then "ave-universals"
  737.  
  738.   function Is_Data_Structure_Use_Required return boolean;
  739.   -- Should we check for enumeration types, records?
  740.  
  741.   function ATTRIBUTE_CHECK return Require_Type;
  742.   -- This function tells whether the style checker notes the
  743.   -- use of attributes.
  744.  
  745.   procedure Average_Subprogram_Size (SMALL_LIMIT : out natural;
  746.                                      LARGE_LIMIT : out natural );
  747.  
  748.   procedure SUBPROGRAM_PARAMETERS (SMALL_LIMIT : out natural;
  749.                                    LARGE_LIMIT : out natural );
  750.  
  751.  
  752.   function CONTROL_NESTING_LEVEL return Natural;
  753.   -- This is the expected depth of nesting of control structures.
  754.  
  755.   function PACKAGE_NESTING_LEVEL return Natural;
  756.   -- This is the expected depth of nesting of packages.
  757.  
  758.   function SUBPROGRAM_NESTING_LEVEL return Natural;
  759.   -- This is the expected depth of nesting of subprograms.
  760.  
  761.   function NUMBER_OF_LOOP_EXITS return natural;
  762.   -- This number is a limit on the number of exits from a loop.
  763.  
  764.   function LINE_SIZE return natural;
  765.   -- This number is a limit on the number of characters in a line.
  766.  
  767.   function CHARACTER_SET return Character_Set_Types;
  768.   -- This enumeration type determines the characters which are
  769.   -- not flagged as style errors.  This is to limit use of
  770.   -- graphic or extended characters which may not transport to
  771.   -- other machines.
  772.  
  773.   function REPRESENTATION_SPECS_ALLOWED return boolean;
  774.   -- This returns true if rep specs are allowed in the style.
  775.  
  776.   function ADDRESS_CLAUSE_ALLOWED return boolean;
  777.   -- This returns true if address clauses are allowed in the style.
  778.  
  779.   function NOTE_PRAGMAS return Pragma_Classes;
  780.   -- This is an enumeration type defining which pragmas (all, system-
  781.   -- dependent, or none) are illegal as defined in the style
  782.  
  783.   function IS_A_PREDEFINED_PRAGMA (name : in DYN.DYN_STRING ) return boolean;
  784.   -- This returns true if the input name is a predefined pragma as listed
  785.   -- in the LRM appendix B.
  786.  
  787.   function IS_A_PROSCRIBED_PACKAGE (name : in DYN.DYN_STRING) return boolean;
  788.   -- This returns true if the input name is a package on the
  789.   -- list of 'stylistically incorrect' packages as defined by the style.
  790.  
  791. end Style_Parameters;
  792. ::::::::::
  793. repgen_spec.ada
  794. ::::::::::
  795. with TEXT_IO;
  796. with STYLE_PARAMETERS;
  797. with TOKENIZER;
  798. with DYN;
  799. package REPORT_GENERATOR is
  800. --------------------------------------------------------------------------
  801. -- Abstract   : This is the package that exports the types and routines
  802. --              necessary to create and write the two report files
  803. --              from the Style_Checker.
  804. --------------------------------------------------------------------------
  805.  
  806.     type TOKEN_COUNT_ARRAY is array (TOKENIZER.TOKEN_TYPE) of NATURAL;
  807.  
  808.     type AVERAGE_KEEPING_RECORD is record
  809.         NUMBER_OF_ITEMS : NATURAL := 0;
  810.         TOTAL_SIZE_OF_ITEMS : NATURAL := 0;
  811.     end record;
  812.  
  813.     type DATA_STRUCTURE_TYPES is (ARRAY_TYPES,
  814.                                   ENUMERATION_TYPES,
  815.                                   RECORD_TYPES);
  816.  
  817.     type DATA_STRUCTURE_TYPES_USED is array (DATA_STRUCTURE_TYPES) of BOOLEAN;
  818.  
  819.     type STRING_NODE;
  820.     type STRING_LIST_TYPE is access STRING_NODE;
  821.     type STRING_NODE is
  822.       record
  823.          NAME : DYN.DYN_STRING;
  824.          NEXT : STRING_LIST_TYPE := null;
  825.       end record;
  826.  
  827.     type CHARACTER_COUNT is array (CHARACTER) of NATURAL;
  828.  
  829.     type REPORT_RECORD is record
  830.         -- Naming Conventions
  831.         INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER           : NATURAL := 0;
  832.         INVALID_CASE_FOR_A_KEYWORD                      : NATURAL := 0;
  833.         ABBREVIATIONS                                   : BOOLEAN := FALSE;
  834.         NAME_SEGMENT_SIZE_DESIRED_MAXIMUM               : NATURAL :=
  835.                                 STYLE_PARAMETERS.AVERAGE_UNDERSCORE_SIZE;
  836.         NAME_SEGMENT_SIZE_ACTUAL                        : FLOAT := 0.0;
  837.         AVERAGE_NAME_SIZE_DESIRED_MINIMUM               : NATURAL :=
  838.                                 STYLE_PARAMETERS.AVERAGE_NAME_SIZE;
  839.         AVERAGE_NAME_SIZE_ACTUAL                        : FLOAT := 0.0;
  840.  
  841.         -- Physical Layout
  842.         OCCURRENCES_OF_MORE_THAN_ONE_STATEMENT_PER_LINE : NATURAL := 0;
  843.         INCONSISTANT_INDENTATION                        : NATURAL := 0;
  844.         MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK          : NATURAL := 0;
  845.         MISSING_PROLOG                                  : NATURAL := 0;
  846.         LOOPS_WITHOUT_NAMES                             : NATURAL := 0;
  847.         PERCENT_OF_BLANK_LINES_DESIRED_MINIMUM          : FLOAT := 0.0;
  848.         PERCENT_OF_BLANK_LINES_ACTUAL                   : FLOAT := 0.0;
  849.  
  850.         -- Information Hiding, Abstraction, Data Use
  851.         PERCENT_OF_LITERALS_IN_BODY_DESIRED_MAXIMUM     : FLOAT :=
  852.                                 STYLE_PARAMETERS.AVERAGE_LITERAL_IN_BODY;
  853.         PERCENT_OF_LITERALS_IN_BODY_ACTUAL              : FLOAT := 0.0;
  854.         PERCENT_OF_UNIVERSAL_TYPES_DESIRED_MAXIMUM      : FLOAT :=
  855.                                 STYLE_PARAMETERS.AVERAGE_UNIVERSAL_USAGE;
  856.         PERCENT_OF_UNIVERSAL_TYPES_ACTUAL               : FLOAT := 0.0;
  857.         DATA_STRUCTURING_TYPES_NOT_USED : DATA_STRUCTURE_TYPES_USED :=
  858.                 (DATA_STRUCTURE_TYPES'FIRST .. DATA_STRUCTURE_TYPES'LAST =>
  859.                  TRUE);
  860.         ATTRIBUTES_USED                                 : BOOLEAN := FALSE;
  861.         OR_ELSES_USED                                   : BOOLEAN := FALSE;
  862.         AND_THENS_USED                                  : BOOLEAN := FALSE;
  863.         EXITS_USED                                      : BOOLEAN := FALSE;
  864.         XORS_USED                                       : BOOLEAN := FALSE;
  865.         ELSIFS_USED                                     : BOOLEAN := FALSE;
  866.         EXCEPTIONS_USED                                 : BOOLEAN := FALSE;
  867.         INS_USED                                        : BOOLEAN := FALSE;
  868.         OUTS_USED                                       : BOOLEAN := FALSE;
  869.         IN_OUTS_USED                                    : BOOLEAN := FALSE;
  870.         PRIVATES_USED                                   : BOOLEAN := FALSE;
  871.         -- Modularity
  872.         AVERAGE_NUMBER_OF_PARAMETERS_DESIRED_MINIMUM    : NATURAL := 0;
  873.         AVERAGE_NUMBER_OF_PARAMETERS_DESIRED_MAXIMUM    : NATURAL := 0;
  874.         INSTANCES_OF_PARAMETERS_BELOW_MINIMUM           : NATURAL := 0;
  875.         INSTANCES_OF_PARAMETERS_ABOVE_MAXIMUM           : NATURAL := 0;
  876.         AVERAGE_SUBPROGRAM_SIZE_DESIRED_MINIMUM         : NATURAL := 0;
  877.         AVERAGE_SUBPROGRAM_SIZE_DESIRED_MAXIMUM         : NATURAL := 0;
  878.         INSTANCES_OF_SIZE_BELOW_MINIMUM                 : NATURAL := 0;
  879.         INSTANCES_OF_SIZE_ABOVE_MAXIMUM                 : NATURAL := 0;
  880.         INSTANCES_OF_TOO_MANY_EXITS                     : NATURAL := 0;
  881.         CONTROL_STRUCTURE_NESTING_DESIRED_MAXIMUM       : NATURAL :=
  882.                                 STYLE_PARAMETERS.CONTROL_NESTING_LEVEL;
  883.         CONTROL_STRUCTURE_NESTING_EXCEEDING_MAXIMUM     : NATURAL := 0;
  884.         PACKAGE_NESTING_DESIRED_MAXIMUM                 : NATURAL :=
  885.                                 STYLE_PARAMETERS.PACKAGE_NESTING_LEVEL;
  886.         PACKAGE_NESTING_EXCEEDING_MAXIMUM               : NATURAL := 0;
  887.         SUBPROGRAM_NESTING_DESIRED_MAXIMUM              : NATURAL :=
  888.                                 STYLE_PARAMETERS.SUBPROGRAM_NESTING_LEVEL;
  889.         SUBPROGRAM_NESTING_EXCEEDING_MAXIMUM            : NATURAL := 0;
  890.  
  891.         -- Comment Usage
  892.         NUMBER_OF_COMMENTS                              : NATURAL := 0;
  893.         AVERAGE_COMMENT_SIZE_DESIRED_MINIMUM            : NATURAL :=
  894.                                 STYLE_PARAMETERS.AVERAGE_COMMENT_SIZE;
  895.         AVERAGE_COMMENT_SIZE_ACTUAL                     : FLOAT := 0.0;
  896.  
  897.         -- Transportability
  898.         NUMBER_OF_LINES_EXCEEDING_LINE_LENGTH           : NATURAL := 0;
  899.         GRAPHIC_CHARACTERS_USED                         : CHARACTER_COUNT :=
  900.                                 (CHARACTER'FIRST..CHARACTER'LAST => 0);
  901.         NON_GRAPHIC_CHARACTERS_USED                     : CHARACTER_COUNT :=
  902.                                 (CHARACTER'FIRST..CHARACTER'LAST => 0);
  903.         ADDRESS_CLAUSES                                 : NATURAL := 0;
  904.         REPRESENTATION_SPECIFICATIONS                   : NATURAL := 0;
  905.         PRAGMAS_USED                           : STRING_LIST_TYPE := null;
  906.         NON_STANDARD_PRAGMAS_USED              : STRING_LIST_TYPE := null;
  907.         PACKAGES_PROCEDURES_WITHED             : STRING_LIST_TYPE := null;
  908.  
  909.         -- Keyword Usage
  910.         KEYWORD_USAGE                   : STYLE_PARAMETERS.KEYWORD_USES;
  911.         TOKEN_COUNT                     : TOKEN_COUNT_ARRAY :=
  912.                                           (TOKENIZER.TOKEN_TYPE'FIRST ..
  913.                                            TOKENIZER.TOKEN_TYPE'LAST => 0);
  914.     end record;
  915.  
  916.     type ERRORS is
  917.           (INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER,
  918.            INVALID_CASE_FOR_A_KEYWORD,
  919.            ABBREVIATION,
  920.  
  921.            -- Physical Layout
  922.  
  923.            MORE_THAN_ONE_STATEMENT_ON_LINE,
  924.            INCONSISTANT_INDENTATION,
  925.            MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK,
  926.            MISSING_PROLOG,
  927.            LOOP_WITHOUT_NAME,
  928.  
  929.            -- Modularity
  930.  
  931.            TOO_FEW_PARAMETERS,
  932.            TOO_MANY_PARAMETERS,
  933.            SUBPROGRAM_SIZE_BELOW_MINIMUM,
  934.            SUBPROGRAM_SIZE_ABOVE_MAXIMUM,
  935.            TOO_MANY_EXITS,
  936.            PACKAGE_NESTED_TOO_DEEP,
  937.            CONTROL_STRUCTURE_NESTED_TOO_DEEP,
  938.            SUBPROGRAM_NESTED_TOO_DEEP,
  939.  
  940.            -- Transportability
  941.  
  942.            LINE_EXCEEDING_LINE_LENGTH,
  943.            GRAPHIC_CHARACTER_USED,
  944.            NON_GRAPHIC_CHARACTER_USED,
  945.            ADDRESS_CLAUSE_USED,
  946.            REPRESENTATION_SPECIFICATION_USED,
  947.            PRAGMA_USED,
  948.            NON_STANDARD_PRAGMA_USED,
  949.  
  950.            -- Other
  951.  
  952.            UNMATCHED_NESTING,
  953.            OTHER);
  954.  
  955.     procedure PUT_FLAW(TO_THIS : in TEXT_IO.FILE_TYPE;
  956.                        BAD_TOKEN : in TOKENIZER.TOKEN;
  957.                        ERROR_MESSAGE : in DYN.DYN_STRING;
  958.                        ERROR_TYPE : in ERRORS := OTHER  );
  959.  
  960.     procedure PUT_FLAW(TO_THIS : in TEXT_IO.FILE_TYPE;
  961.                        BAD_TOKEN : in TOKENIZER.TOKEN;
  962.                        ERROR_MESSAGE : in STRING;
  963.                        ERROR_TYPE : in ERRORS := OTHER  );
  964.  
  965.     procedure GENERATE_REPORT(FROM_THIS : in REPORT_RECORD;
  966.                               TO_THIS : in TEXT_IO.FILE_TYPE;
  967.                               FILE_NAME : in DYN.DYN_STRING );
  968.  
  969.  
  970.     procedure INSERT_INTO_LIST ( LIST : in out STRING_LIST_TYPE;
  971.                                  ELEMENT : DYN.DYN_STRING );
  972.  
  973. end REPORT_GENERATOR;
  974. ::::::::::
  975. stack_package.ada
  976. ::::::::::
  977. -------------------------PROLOGUE---------------------------------------
  978. --                                                                    -*
  979. -- Unit name    : STACK_PACKAGE
  980. -- Author       : Tom Duke
  981. -- Date created : Sept. 7, 1984
  982. -- Last update  : Sept. 20, 1984
  983. --                                                                    -*
  984. ------------------------------------------------------------------------
  985. --                                                                    -*
  986. -- Abstract     : This is a generic package that provides the types,
  987. ----------------: procedures, and exceptions to define an abstract stack
  988. ----------------: and its corresponding operations.  Using an
  989. ----------------: instantiation of this generic package, one can declare
  990. ----------------: multiple versions of a stack of type HELP_INFO_STACK.
  991. ----------------: The stack operations provided include:
  992. ----------------: 1. clear the stack,
  993. ----------------: 2. pop the stack,
  994. ----------------: 3. push an element onto the stack, and
  995. ----------------: 4. access the top element on the stack.
  996. --                                                                    -*
  997. ------------------------------------------------------------------------
  998. --
  999. -- Mnemonic     :
  1000. -- Name         :
  1001. -- Release date :
  1002. ------------------ Revision history ------------------------------------
  1003. --
  1004. -- DATE  AUTHOR   HISTORY
  1005. --
  1006. --
  1007. --
  1008. --------------------END-PROLOGUE----------------------------------------
  1009.  
  1010. generic
  1011.  
  1012.   type ELEMENTS is private;
  1013.   SIZE : POSITIVE;
  1014.  
  1015. package STACK_PACKAGE is
  1016.  
  1017.   type HELP_INFO_STACK is  private;
  1018.  
  1019.  
  1020.   function TOP_ELEMENT( STACK  : in  HELP_INFO_STACK )
  1021.     return ELEMENTS;
  1022.  
  1023.   function STACK_IS_EMPTY( STACK : in HELP_INFO_STACK )
  1024.     return BOOLEAN;
  1025.  
  1026.   procedure CLEAR_STACK( STACK : in out HELP_INFO_STACK );
  1027.  
  1028.  
  1029.   procedure PUSH       ( FRAME : in ELEMENTS;
  1030.                          STACK : in out HELP_INFO_STACK );
  1031.  
  1032.   procedure POP        ( FRAME : out ELEMENTS;
  1033.                          STACK : in out HELP_INFO_STACK );
  1034.  
  1035.   NULL_STACK      : exception;
  1036.   STACK_OVERFLOW  : exception;
  1037.   STACK_UNDERFLOW : exception;
  1038.  
  1039.  
  1040. private
  1041.  
  1042.   type STACK_LIST is array ( 1 .. SIZE ) of ELEMENTS;
  1043.  
  1044.   type HELP_INFO_STACK  is
  1045.      record
  1046.       CONTENTS       :  STACK_LIST;
  1047.       TOP            :  NATURAL range NATURAL'FIRST .. SIZE := NATURAL'FIRST;
  1048.      end record;
  1049.  
  1050. end STACK_PACKAGE;
  1051.  
  1052.  
  1053. -------------------------------------------------------------------------
  1054.  
  1055.  
  1056. package body STACK_PACKAGE is
  1057.  
  1058. ---------------
  1059. --  function TOP_ELEMENT  --  This function returns the value of the top
  1060. --                            element on the stack.  It does not return a
  1061. --  pointer to the top element.  If the stack is empty, a constraint error
  1062. --  occurs.  The exception handler will then raise the NULL_STACK
  1063. --  exception and pass it to the calling procedure.
  1064. ---------------
  1065.   function TOP_ELEMENT( STACK : in  HELP_INFO_STACK ) return ELEMENTS is
  1066.   begin
  1067.    return STACK.CONTENTS(STACK.TOP);
  1068.    exception
  1069.       when CONSTRAINT_ERROR =>
  1070.          raise NULL_STACK;
  1071.       when others =>
  1072.          raise;
  1073.   end TOP_ELEMENT;
  1074.  
  1075.   ----------
  1076.   --  Is stack empty?
  1077.   ----------
  1078.   function STACK_IS_EMPTY( STACK : in HELP_INFO_STACK )
  1079.     return BOOLEAN is
  1080.   begin
  1081.     return (STACK.TOP = NATURAL'FIRST);
  1082.   exception
  1083.     when OTHERS =>
  1084.          raise;
  1085.   end STACK_IS_EMPTY;
  1086.  
  1087.  
  1088. ---------------
  1089. --  procedure CLEAR_STACK  --  This procedure resets the stack pointer, TOP,
  1090. --                             to a value representing an empty stack.
  1091. ---------------
  1092.   procedure CLEAR_STACK( STACK : in out HELP_INFO_STACK ) is
  1093.   begin
  1094.    STACK.TOP := NATURAL'FIRST;
  1095.   end CLEAR_STACK;
  1096.  
  1097.  
  1098. ---------------
  1099. --  procedure PUSH  --  This procedure attempts to push another element onto
  1100. --                      the stack.  If the stack is full, a constraint error
  1101. --  occurs.  The exception handler will then raise the STACK_OVERFLOW
  1102. --  exception and pass it to the calling procedure.
  1103. ---------------
  1104.   procedure PUSH       ( FRAME : in ELEMENTS;
  1105.                          STACK : in out HELP_INFO_STACK ) is
  1106.   begin
  1107.    STACK.TOP := STACK.TOP + 1;
  1108.    STACK.CONTENTS(STACK.TOP) := FRAME;
  1109.    exception
  1110.       when CONSTRAINT_ERROR =>
  1111.          raise STACK_OVERFLOW;
  1112.       when others =>
  1113.          raise;
  1114.   end PUSH;
  1115.  
  1116.  
  1117. ---------------
  1118. --  procedure POP  --  This procedure attempts to pop an element from
  1119. --                     the stack.  If the stack is empty, a constraint error
  1120. --  occurs.  The exception handler will then raise the STACK_UNDERFLOW
  1121. --  exception and pass it to the calling procedure.
  1122. ---------------
  1123.   procedure POP        ( FRAME : out ELEMENTS;
  1124.                          STACK : in out HELP_INFO_STACK ) is
  1125.   begin
  1126.    FRAME := STACK.CONTENTS(STACK.TOP);
  1127.    STACK.TOP := STACK.TOP - 1;
  1128.    exception
  1129.       when CONSTRAINT_ERROR =>
  1130.          raise STACK_UNDERFLOW;
  1131.       when others =>
  1132.          raise;
  1133.   end POP;
  1134.  
  1135. end STACK_PACKAGE;
  1136. ::::::::::
  1137. token_definition.ada
  1138. ::::::::::
  1139. -- 
  1140. -- Token-Specific Information for the Spelling Checker
  1141. -- 
  1142. package TOKEN_DEFINITION is
  1143. --------------------------------------------------------------------------
  1144. -- Abstract   : TOKEN_DEFINITION contains the definition of a token
  1145. --               (see type TOKEN_TYPE), including the length of its
  1146. --               word which may be easily changed (see TOKEN_LENGTH).
  1147. -- 
  1148. --              IS_SPECIAL_CHAR is also provided since it is a commonly-
  1149. --               used routine which is employed by more than one package.
  1150. --------------------------------------------------------------------------
  1151.  
  1152. -- 
  1153. -- Definition of a Token (Word)
  1154. -- 
  1155.     TOKEN_LENGTH : constant NATURAL := 25; -- number of characters
  1156.     subtype TOKEN_STRING is STRING (1 .. TOKEN_LENGTH);
  1157.     type TOKEN_TYPE is
  1158.     record
  1159.         WORD   : TOKEN_STRING;
  1160.         LENGTH : NATURAL;
  1161.     end record;
  1162.  
  1163.  
  1164.     function IS_SPECIAL_CHAR (CH : CHARACTER) return BOOLEAN;
  1165. --------------------------------------------------------------------------
  1166. -- Abstract   : Returns a BOOLEAN indicating if the indicated character
  1167. --               is one of the special characters which may be found
  1168. --               within a word or at the end of a word.
  1169. --------------------------------------------------------------------------
  1170. -- Parameters : CH             - character to test
  1171. --------------------------------------------------------------------------
  1172.  
  1173. end TOKEN_DEFINITION;
  1174.  
  1175. package body TOKEN_DEFINITION is
  1176.  
  1177.     SPECIAL_CHARS : constant STRING (1 .. 3) := "-'.";
  1178.  
  1179.     function IS_SPECIAL_CHAR (CH : CHARACTER) return BOOLEAN is
  1180.     begin
  1181.     for I in SPECIAL_CHARS'FIRST .. SPECIAL_CHARS'LAST loop
  1182.         if CH = SPECIAL_CHARS (I) then
  1183.         return TRUE;
  1184.         end if;
  1185.     end loop;
  1186.     return FALSE;
  1187.     end IS_SPECIAL_CHAR;
  1188.  
  1189. end TOKEN_DEFINITION;
  1190. ::::::::::
  1191. manager.ada
  1192. ::::::::::
  1193. ------------------------------------------------------------
  1194. --
  1195. -- Abstract     :   This unit outlines the procedures and functions
  1196. --              :   contained in this package.  The visible section
  1197. --              :   provides the interfaces necessary for commun-
  1198. --              :   ication with the various subunits contained in
  1199. --              :   the package.
  1200. --              :
  1201. --              :   The package is concerned with the handling of the
  1202. --              :   data structures that are utilized for the storage of the
  1203. --              :   information, (words and acronyms), which is used
  1204. --              :   within the Spelling Corrector tool.
  1205. --
  1206. ----------------------------------------------------------------
  1207.  
  1208. with TEXT_IO,
  1209.      TOKEN_DEFINITION;
  1210. package DICTIONARY_MANAGER is
  1211.  
  1212. --Establishes the types of dictionaries available
  1213.   type DICTIONARY_TYPE is (MASTER,ACRONYM,USER);
  1214.  
  1215.   type DICTIONARY_PTR  is private;
  1216.  
  1217.   subtype FILE_NAME_TYPE  is TEXT_IO.FILE_TYPE;
  1218.  
  1219. --A test variable to be removed later
  1220. WORD_COUNTER : NATURAL;
  1221. --
  1222.  
  1223.   NO_MORE_WORDS          : exception; --raised when the NEXT_WORD
  1224.                                       --procedure can no longer return
  1225.                                       --the required number of words or
  1226.                                       --the procedure is called with a
  1227.                                       --word count of 0
  1228.  
  1229.   BAD_WORD               : exception; --An illegal word format
  1230.                                       --raised in the HASH_VALUE function
  1231.   DICTIONARY_ERROR       : exception; --A nonexistent dictionary
  1232.                                       --or dictionary error
  1233.   WORD_NOT_VALID         : exception; --A word not in the dictionary
  1234.                                       --raised in the DELETE_WORD procedure
  1235.   HARDWARE_FAILURE       : exception; --Failure of IO devices
  1236.  
  1237. -- The following procedures and functions are documented in the
  1238. -- package body (DICTIONARY_MANAGER)
  1239.  
  1240.   procedure CREATE_DICTIONARY(DICTIONARY_KIND : in DICTIONARY_TYPE;
  1241.                               DICTIONARY_IN : out DICTIONARY_PTR;
  1242.                               FILENAME : in STRING);
  1243.  
  1244.   procedure TOKEN_IS_FOUND(IN_DICTIONARY : out DICTIONARY_PTR;
  1245.                            WORD : in TOKEN_DEFINITION.TOKEN_TYPE;
  1246.                            FOUND : out BOOLEAN);
  1247.  
  1248. private
  1249.  
  1250.   type WORD_RECORD;
  1251.  
  1252.   type WORD_RECORD_PTR is access WORD_RECORD;
  1253.  
  1254.   type WORD_RECORD is
  1255.     record
  1256.       TOKEN   : TOKEN_DEFINITION.TOKEN_TYPE;
  1257.       NEXT    : WORD_RECORD_PTR;
  1258.     end record;
  1259.  
  1260.   MAX_HASH_BUCKETS : constant POSITIVE := 101;
  1261.  
  1262.   subtype HASH_BUCKET_TYPE is POSITIVE
  1263.                               range POSITIVE'FIRST..MAX_HASH_BUCKETS;
  1264.  
  1265.   type DICTIONARY_HASH_STRUCTURE is array (HASH_BUCKET_TYPE)
  1266.                                     of WORD_RECORD_PTR;
  1267.  
  1268.   type DICTIONARY_RECORD;
  1269.  
  1270.   type DICTIONARY_PTR is access DICTIONARY_RECORD;
  1271.  
  1272.   type DICTIONARY_RECORD is
  1273.     record
  1274.       DICTIONARY_NAME : DICTIONARY_TYPE;
  1275.       ENABLED         : BOOLEAN := FALSE;
  1276.       HASH_TABLE      : DICTIONARY_HASH_STRUCTURE;
  1277.       NEXT_DICTIONARY : DICTIONARY_PTR;
  1278.       ALTER_FLAG      : BOOLEAN := FALSE;
  1279.     end record;
  1280.  
  1281. end DICTIONARY_MANAGER;
  1282.  
  1283. ----------------------------------------------------------------
  1284. --
  1285. -- Abstract     :   This unit is the STUB for the dictionary manager
  1286. --
  1287. ----------------------------------------------------------------
  1288.  
  1289. package body  DICTIONARY_MANAGER is
  1290.  
  1291.   procedure CREATE_DICTIONARY(DICTIONARY_KIND : in DICTIONARY_TYPE;
  1292.                               DICTIONARY_IN : out DICTIONARY_PTR;
  1293.                               FILENAME : in STRING) is
  1294.   begin
  1295.     return;
  1296.   end CREATE_DICTIONARY;
  1297.  
  1298.   procedure TOKEN_IS_FOUND(IN_DICTIONARY : out DICTIONARY_PTR;
  1299.                            WORD : in TOKEN_DEFINITION.TOKEN_TYPE;
  1300.                            FOUND : out BOOLEAN) is
  1301.   begin
  1302.     FOUND := TRUE;
  1303.   end TOKEN_IS_FOUND;
  1304.  
  1305. end DICTIONARY_MANAGER;
  1306. ::::::::::
  1307. help_file_spec.ada
  1308. ::::::::::
  1309. package HELP is
  1310. --------------------------------------------------------------------------
  1311. -- Abstract   : This is a help package.  It gives access to a help routine
  1312. --              that can be called from the Style_Checker.
  1313. --------------------------------------------------------------------------
  1314.  
  1315.     subtype LEVEL_TYPE is string(1..4) ;
  1316.  
  1317.     HELP  : constant LEVEL_TYPE := "HELP";
  1318.  
  1319.     procedure HELP_SCREEN (LEVEL  : LEVEL_TYPE; HELP_FILE_NAME : string);
  1320.  
  1321.  
  1322.  -- exceptions
  1323.  
  1324.     HELP_OPEN_ERROR : exception;
  1325.     HELP_FILE_ERROR : exception;
  1326.     HELP_FORMAT_ERROR : exception;
  1327.  
  1328. end HELP;
  1329. ::::::::::
  1330. command_line.ada
  1331. ::::::::::
  1332. --
  1333. -- COMMAND_LINE_HANDLER by Richard Conn, TI Ada Technology Branch
  1334. -- 27 Feb 85
  1335. --
  1336. package COMMAND_LINE_HANDLER is
  1337. --------------------------------------------------------------------------
  1338. -- Abstract   : This package contains routines which return words
  1339. --               from the command line tail (parameters following
  1340. --               the command line verb).  It expects a file to have
  1341. --               been created externally which contains these words,
  1342. --               one word per line.
  1343. --------------------------------------------------------------------------
  1344.  
  1345.     NO_COMMAND_LINE_FILE : exception;
  1346.     NO_MORE_WORDS        : exception;
  1347.  
  1348.  
  1349.     procedure NEXT_WORD (COMMAND_LINE_FILE_NAME : in STRING;
  1350.                          WORD : out STRING; LENGTH : out NATURAL);
  1351. --------------------------------------------------------------------------
  1352. -- Abstract   : NEXT_WORD returns the next word from the command
  1353. --               line tail.  If there are no more words, NO_MORE_WORDS
  1354. --               is raised.  If there is no command line file,
  1355. --               NO_COMMAND_LINE_FILE is raised.
  1356. --------------------------------------------------------------------------
  1357. -- Parameters : WORD           - string containing the next word
  1358. --              LENGTH         - number of chars in next word
  1359. --------------------------------------------------------------------------
  1360.  
  1361.  
  1362.     procedure RESET;
  1363. --------------------------------------------------------------------------
  1364. -- Abstract   : If the file containing the command line's words
  1365. --               is open, this file is closed.  The net effect is
  1366. --               that the next invocation of NEXT_WORD will return
  1367. --               the first word of the command line tail.
  1368. --------------------------------------------------------------------------
  1369.  
  1370. end COMMAND_LINE_HANDLER;
  1371.  
  1372.  
  1373. with TEXT_IO;
  1374. package body COMMAND_LINE_HANDLER is
  1375.  
  1376.     line_obtained : boolean := false;
  1377.  
  1378.     procedure RESET is
  1379.     begin
  1380.         line_obtained := false;
  1381.     end RESET;
  1382.  
  1383.     procedure NEXT_WORD (COMMAND_LINE_FILE_NAME : in STRING;
  1384.                          WORD : out STRING; LENGTH : out NATURAL) is
  1385.     begin
  1386.         IF NOT line_obtained THEN
  1387.             text_io.put ("Name of File to Process> ");
  1388.             text_io.get_line (word, length);
  1389.         line_obtained := true;
  1390.         ELSE
  1391.             RAISE no_more_words;
  1392.         END IF;
  1393.     end NEXT_WORD;
  1394.  
  1395. end COMMAND_LINE_HANDLER;
  1396. ::::::::::
  1397. HELPINFO_SPEC.ADA
  1398. ::::::::::
  1399.  
  1400. ------------------------------------------------------------------------
  1401. --                                                                    -*
  1402. -- Abstract     : The HELP_INFO_SUPPORT package provides the constants
  1403. ----------------: and types to support the implementation of the AIM
  1404. ----------------: Help and Info utilities.
  1405. --                                                                    -*
  1406. ------------------------------------------------------------------------
  1407.  
  1408.  
  1409. package HELP_INFO_SUPPORT is
  1410.  
  1411.  
  1412. MAX_LINE_LENGTH              :  constant INTEGER := 80;
  1413. MAX_LEVEL                    :  constant INTEGER := 10;
  1414.  
  1415. TOKEN_SEPARATER              :  constant CHARACTER := ' ';
  1416.  
  1417.  
  1418. -- types and pointers for APPEND_TO_DISPLAY ------------
  1419.  
  1420. subtype FILE_TEXT_LINE is string(1..MAX_LINE_LENGTH);
  1421.  
  1422. type TEXT_LINE;
  1423. type TEXT_LINK  is access TEXT_LINE;
  1424. type TEXT_LINE is
  1425.      record
  1426.             TEXT_LINE        : FILE_TEXT_LINE;
  1427.             LINE_LENGTH      : natural := 0;
  1428.             NEXT_LINE        : TEXT_LINK := null;
  1429.     end record;
  1430.  
  1431. TOP_LINE: TEXT_LINK := new TEXT_LINE;
  1432. CURRENT_LINE: TEXT_LINK := TOP_LINE;
  1433. PREVIOUS_LINE: TEXT_LINK := TOP_LINE;
  1434. IS_FIRST_TIME: boolean := true;
  1435.  
  1436. -----------------------------------------------------------
  1437.  
  1438. subtype LEVEL_RANGE is NATURAL range 0..MAX_LEVEL;
  1439.  
  1440. subtype HELP_INFO_TEXT_LINE is STRING(1..MAX_LINE_LENGTH);
  1441.  
  1442. ----------
  1443. --  type declarations for the parsed input buffer
  1444. ----------
  1445.  
  1446. subtype LINE_LENGTH is NATURAL range 0..MAX_LINE_LENGTH;
  1447. subtype LINE_INDEX is POSITIVE range 1..MAX_LINE_LENGTH;
  1448. type TOKEN_RECORD is
  1449.    record
  1450.       TOKEN      : HELP_INFO_TEXT_LINE;
  1451.       LENGTH     : LINE_LENGTH;
  1452.       BUFFER_POS : POSITIVE;    -- 1..aim_support.max_data_length
  1453.    end record;
  1454. subtype NUMBER_OF_TOKENS_RANGE is NATURAL
  1455.                       range 0..MAX_LEVEL;
  1456. subtype TOKEN_ARRAY_RANGE is POSITIVE
  1457.                       range 1..MAX_LEVEL;
  1458. type TOKEN_ARRAY is array( TOKEN_ARRAY_RANGE ) of TOKEN_RECORD;
  1459.  
  1460. ----------
  1461. --  Subtype and type which define the structure of the table used
  1462. --  for implicit conversion of characters from lowercase to uppercase.
  1463. ----------
  1464. subtype LOWER_CASE_RANGE is CHARACTER range ASCII.LC_A .. ASCII.LC_Z;
  1465. type CASE_CONVERSION_TABLE is array( LOWER_CASE_RANGE ) of CHARACTER;
  1466.  
  1467. ----------
  1468. --  Variables used when working with the INPUT_TOKEN_TABLE.
  1469. ----------
  1470. TOKEN_LENGTH    : LINE_LENGTH;
  1471. TOKEN_STRING    : HELP_INFO_TEXT_LINE;
  1472. TOKEN_POS       : POSITIVE;
  1473.  
  1474. ----------
  1475. --  Pointer to the next character position of the user input string
  1476. --  to be accessed during the procedures PARSE and GET_NEXT_INFO_TOKEN.
  1477. ----------
  1478. INPUT_STRING_POS  : POSITIVE;
  1479.  
  1480. ----------
  1481. --  Table used to store individual tokens, their length, and their
  1482. --  position in the user's input string.
  1483. ----------
  1484. INPUT_TOKEN_TABLE : TOKEN_ARRAY;
  1485.  
  1486. ----------
  1487. --  Counter for saving the number of tokens extracted from the user's
  1488. --  input string.
  1489. ----------
  1490. NUMBER_OF_TOKENS  : NUMBER_OF_TOKENS_RANGE;
  1491.  
  1492. ----------
  1493. --  As the variable type indicates, the case conversion table used
  1494. --  for implicit conversion from lowercase to uppercase.
  1495. ----------
  1496. UPPER_CASE : CASE_CONVERSION_TABLE := "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  1497.  
  1498.  
  1499. KEYWORD_NOT_FOUND : exception;
  1500.  
  1501. -----------------------------------------------------------
  1502.  
  1503. procedure APPEND_TO_DISPLAY(LINE       : in STRING;
  1504.                             CHAR_COUNT: in natural);
  1505.  
  1506.  
  1507. procedure IDENTIFY_KEYWORD(
  1508.           TOKEN_STRING : in HELP_INFO_TEXT_LINE;
  1509.           TOKEN_LENGTH : in LINE_LENGTH;
  1510.           KEYWORD      : in HELP_INFO_TEXT_LINE );
  1511.  
  1512.  
  1513. procedure GET_NEXT_TOKEN(
  1514.             INPUT_STRING : in  STRING;
  1515.             NEXT_STRING  : out HELP_INFO_TEXT_LINE;
  1516.             NEXT_LENGTH  : out LINE_LENGTH;
  1517.             NEXT_POS     : out POSITIVE );
  1518.  
  1519.  
  1520. procedure PARSE(INPUT_STRING : in STRING);
  1521.  
  1522.  
  1523. end HELP_INFO_SUPPORT;
  1524. ::::::::::
  1525. HELPINFO_BODY.ADA
  1526. ::::::::::
  1527.  
  1528. ------------------------------------------------------------------------
  1529. --                                                                    -*
  1530. -- Abstract     : The HELP_INFO_SUPPORT package provides the constants
  1531. ----------------: and types to support the implementation of the AIM
  1532. ----------------: Help and Info utilities.
  1533. --                                                                    -*
  1534. ------------------------------------------------------------------------
  1535.  
  1536. package body HELP_INFO_SUPPORT is
  1537.  
  1538.  
  1539. procedure APPEND_TO_DISPLAY(LINE       : in STRING;
  1540.                             CHAR_COUNT: in natural) is
  1541.  
  1542. begin
  1543.  
  1544.   if LINE'length <= FILE_TEXT_LINE'length then
  1545.     CURRENT_LINE.TEXT_LINE := FILE_TEXT_LINE'(others => ' ');
  1546.     CURRENT_LINE.TEXT_LINE(1..LINE'length) := LINE;
  1547.     CURRENT_LINE.LINE_LENGTH := CHAR_COUNT;
  1548.   else
  1549.     CURRENT_LINE.TEXT_LINE := LINE(1..FILE_TEXT_LINE'length);
  1550.     CURRENT_LINE.LINE_LENGTH := FILE_TEXT_LINE'length;
  1551.   end if;
  1552.  
  1553.   PREVIOUS_LINE.NEXT_LINE := CURRENT_LINE;
  1554.   CURRENT_LINE.NEXT_LINE := null;
  1555.   PREVIOUS_LINE := CURRENT_LINE;
  1556.   CURRENT_LINE := new TEXT_LINE;
  1557.  
  1558. exception
  1559.    when others =>
  1560.       raise;
  1561. end APPEND_TO_DISPLAY;
  1562.  
  1563.  
  1564. ----------
  1565. --  The procedure IDENTIFY_KEYWORD compares the parameter TOKEN_STRING
  1566. --                                 to the parameter KEYWORD in an
  1567. --  attempt to identify a match.  The global array UPPER_CASE is used
  1568. --  to convert the input character to upper case for comparison purposes.
  1569. --  Note that the input token string actually remains unchanged.
  1570. --     The logic assumes that if the character position pointer TEST_POS
  1571. --  is incremented past the value of the parameter TOKEN_LENGTH (the
  1572. --  actual length of the input token string) then the TOKEN_STRING must
  1573. --  be valid.  This logic allows for abbreviations as small as one character
  1574. --  to be identified.
  1575. --     If a character mismatch or the CONSTRAINT_ERROR exception is raised,
  1576. --  the exception KEYWORD_NOT_FOUND is raised.
  1577. ----------
  1578. procedure IDENTIFY_KEYWORD(
  1579.           TOKEN_STRING : in HELP_INFO_TEXT_LINE;
  1580.           TOKEN_LENGTH : in LINE_LENGTH;
  1581.           KEYWORD      : in HELP_INFO_TEXT_LINE ) is
  1582.  
  1583. TEST_POS : POSITIVE;             --  character test position
  1584. DONE     : BOOLEAN;
  1585.  
  1586. begin
  1587.    TEST_POS := 1;
  1588.    DONE := FALSE;
  1589.    while TEST_POS <= TOKEN_LENGTH and then not DONE loop
  1590.       case TOKEN_STRING(TEST_POS) is
  1591.          when LOWER_CASE_RANGE =>
  1592.             if UPPER_CASE(TOKEN_STRING(TEST_POS)) = KEYWORD(TEST_POS) then
  1593.                TEST_POS := TEST_POS + 1;
  1594.             else
  1595.                DONE := TRUE;
  1596.             end if;
  1597.          when others =>
  1598.             if TOKEN_STRING(TEST_POS) = KEYWORD(TEST_POS) then
  1599.                TEST_POS := TEST_POS + 1;
  1600.             else
  1601.                DONE := TRUE;
  1602.             end if;
  1603.       end case;
  1604.    end loop;
  1605.    if TEST_POS <= TOKEN_LENGTH then
  1606.       raise KEYWORD_NOT_FOUND;
  1607.    end if;
  1608.  
  1609. exception
  1610.    when CONSTRAINT_ERROR =>
  1611.       raise KEYWORD_NOT_FOUND;
  1612.    when KEYWORD_NOT_FOUND =>
  1613.       raise;
  1614.    when others =>
  1615.       raise;
  1616.  
  1617. end IDENTIFY_KEYWORD;
  1618.  
  1619.  
  1620. ----------
  1621. --  The procedure GET_NEXT_TOKEN extracts, from INPUT_STRING, the
  1622. --                                    next character(s) bounded by a
  1623. --  valid token separater and another valid token separater or the end
  1624. --  of the string.  This procedure assumes that INPUT_STRING_POS is
  1625. --  currently positioned between tokens (pointing at a separater
  1626. --  character) or is positioned at the first character of some token in
  1627. --  the INPUT_STRING.
  1628. --     The exception CONSTRAINT_ERROR will be raised when the global
  1629. --  variable INPUT_STRING_POS (of type POSITIVE)
  1630. --  is greater than the length of INPUT_STRING.  Therefore, this
  1631. --  exception is not propagated upward but, is handled to identify the
  1632. --  last token in the INPUT_STRING and its length.
  1633. --     The expected format of INPUT_STRING is:
  1634. --
  1635. --                  [^^^]AAA[^^^AAA...][^^^][<CR>]
  1636. --
  1637. --  where
  1638. --          ^^^   represents any number of separaters (spaces or less),
  1639. --
  1640. --          AAA   represents any number of characters greater than spaces,
  1641. --
  1642. --          ...   indicates the preceeding pattern may be repeated,
  1643. --
  1644. --          [ ]   indicates an optional entry in the string,
  1645. --
  1646. --          <CR>  represents the string delimiter,
  1647. --                normally ASCII.CR or ASCII.LF.
  1648. --
  1649. ----------
  1650. procedure GET_NEXT_TOKEN(
  1651.             INPUT_STRING : in  STRING;
  1652.             NEXT_STRING  : out HELP_INFO_TEXT_LINE;
  1653.             NEXT_LENGTH  : out LINE_LENGTH;
  1654.             NEXT_POS     : out POSITIVE ) is
  1655.  
  1656. TEST_POS    : LINE_INDEX;     -- character test position
  1657. TEMP_STRING : HELP_INFO_TEXT_LINE := (others => ' ');
  1658.  
  1659. begin
  1660.  
  1661.    TEST_POS := 1;
  1662. ----------
  1663. --  Find first non-separater character.  Will raise CONSTRAINT_ERROR
  1664. --  if INPUT_STRING has trailing spaces with no delimiter.  The
  1665. --  exception block correctly handles this situation.
  1666. ----------
  1667.    NEXT_POS := INPUT_STRING_POS;
  1668.    while INPUT_STRING_POS <= INPUT_STRING'last and then
  1669.          INPUT_STRING(INPUT_STRING_POS) <= TOKEN_SEPARATER loop
  1670.       INPUT_STRING_POS := INPUT_STRING_POS + 1;
  1671.    end loop;
  1672.    NEXT_POS := INPUT_STRING_POS;
  1673.  
  1674. ----------
  1675. --  Extract next token string from input buffer.  A string delimiter,
  1676. --  normally ASCII.CR or ASCII.LF, is expected after the last token.
  1677. --  If no delimiter exists, a CONSTRINT_ERROR will be raised at the
  1678. --  end of the last token in the string.
  1679. ----------
  1680.    while INPUT_STRING_POS <= INPUT_STRING'last and then
  1681.          INPUT_STRING(INPUT_STRING_POS) > TOKEN_SEPARATER loop
  1682.       TEMP_STRING(TEST_POS) := INPUT_STRING(INPUT_STRING_POS);
  1683.       TEST_POS := TEST_POS + 1;
  1684.       INPUT_STRING_POS := INPUT_STRING_POS + 1;
  1685.    end loop;
  1686.    NEXT_LENGTH := TEST_POS - 1;
  1687.    NEXT_STRING := TEMP_STRING;
  1688.  
  1689. exception
  1690.    when CONSTRAINT_ERROR =>
  1691.       NEXT_LENGTH := 0;                 --  throw away last token
  1692.       NEXT_STRING := TEMP_STRING;
  1693.    when others =>
  1694.       raise;
  1695.  
  1696. end GET_NEXT_TOKEN;
  1697.  
  1698.  
  1699. ----------
  1700. --  The procedure PARSE calls the procedure GET_NEXT_TOKEN to extract
  1701. --                      individual tokens from the parameter INPUT_STRING
  1702. --  and places these tokens in the INPUT_TOKEN_TABLE along with their
  1703. --  length and position within the INPUT_STRING.
  1704. --     The exception CONSTRAINT_ERROR is trapped to prevent a premature
  1705. --  exit from the info utility.  This exception will occur if the user
  1706. --  entered more than the allowable number of tokens, as defined by the
  1707. --  subtype TOKEN_ARRAY_RANGE.
  1708. --     It is expected that INPUT_STRING will not contain characters with
  1709. --  an ascii code less than TOKEN_SEPARATER (space character) except for
  1710. --  ASCII.HT (between tokens only) and ASCII.CR or ASCII.LF (possible
  1711. --  string delimiters).  If any other character less than TOKEN_SEPARATER
  1712. --  is encountered, the character is treated as a string delimiter.
  1713. ----------
  1714. procedure PARSE(INPUT_STRING : in STRING) is
  1715.  
  1716. begin
  1717.    NUMBER_OF_TOKENS := 0;
  1718.    INPUT_STRING_POS := 1;
  1719.    TOKEN_LENGTH := 1;
  1720.    while INPUT_STRING_POS <= INPUT_STRING'LENGTH
  1721.          and then TOKEN_LENGTH > 0 loop
  1722.       GET_NEXT_TOKEN(INPUT_STRING,
  1723.                      TOKEN_STRING,
  1724.                      TOKEN_LENGTH,
  1725.                      TOKEN_POS);
  1726.       if TOKEN_LENGTH > 0 and then
  1727.             NUMBER_OF_TOKENS < MAX_LEVEL then
  1728.          NUMBER_OF_TOKENS := NUMBER_OF_TOKENS + 1;
  1729.          INPUT_TOKEN_TABLE(NUMBER_OF_TOKENS).TOKEN := TOKEN_STRING;
  1730.          INPUT_TOKEN_TABLE(NUMBER_OF_TOKENS).LENGTH := TOKEN_LENGTH;
  1731.          INPUT_TOKEN_TABLE(NUMBER_OF_TOKENS).BUFFER_POS := TOKEN_POS;
  1732.       else
  1733.          exit;
  1734.       end if;
  1735.    end loop;
  1736. --  exception
  1737. -- when CONSTRAINT_ERROR =>
  1738.       --  occurs when NUMBER_OF_TOKENS > MAX_LEVEL
  1739. --    null;
  1740. -- when others =>
  1741. --    raise;
  1742. end PARSE;
  1743.  
  1744. end HELP_INFO_SUPPORT;
  1745. ::::::::::
  1746. HELP_SPEC.ADA
  1747. ::::::::::
  1748. -------------------------PROLOGUE---------------------------------------
  1749. --                                                                    -*
  1750. -- Unit name    :  HELP_UTILITY                         spec
  1751. -- Author       :  BASKETTE
  1752. -- Date created :  28 January 1985
  1753. -- Last update  :
  1754. --                                                                    -*
  1755. ------------------------------------------------------------------------
  1756. --                                                                    -*
  1757. -- Abstract     : VAX like HELP Utility. Thera are three procedures:
  1758. ----------------: 1) Initialize - reads the help file into a data structure
  1759. ----------------: 2) Help_Me - the help driver
  1760. ----------------: 3) Terminate_help - terminates the help utility
  1761. ----------------:
  1762. ----------------: A function is provided to check if help is active
  1763. --                                                                    -*
  1764. ------------------------------------------------------------------------
  1765. --
  1766. -- Mnemonic     :
  1767. -- Name         :
  1768. -- Release date :
  1769. ------------------ Revision history ------------------------------------
  1770. --
  1771. -- DATE  AUTHOR   HISTORY
  1772. --
  1773. --
  1774. --
  1775. --------------------END-PROLOGUE----------------------------------------
  1776.  
  1777. package HELP_UTILITY is
  1778.  
  1779.     ILLEGAL_FORMAT_FOR_HELP_FILE: exception;
  1780.     HELP_FILE_DOES_NOT_EXIST:     exception;
  1781.     CANNOT_OPEN_HELP_FILE:        exception;
  1782.     HELP_FILE_NOT_INITIALIZED:    exception;
  1783.     NOTHING_TO_OUTPUT:            exception;
  1784.  
  1785.     procedure INITIALIZE(HELP_FILE_NAME: in string);
  1786.  
  1787.     procedure HELP_ME(CLI_BUFFER: in string);
  1788.  
  1789.     procedure GET_TEXT_LINE(LINE: out string;
  1790.                             CHAR_COUNT: out natural;
  1791.                             IS_LAST: out boolean);
  1792.  
  1793.     procedure EXIT_HELP;
  1794.  
  1795.     procedure RESET_HELP;
  1796.  
  1797.     function HELP_IS_TERMINATED return boolean;
  1798.  
  1799. end HELP_UTILITY;
  1800. ::::::::::
  1801. HELP_BODY.ADA
  1802. ::::::::::
  1803. -------------------------PROLOGUE---------------------------------------
  1804. --                                                                    -*
  1805. -- Unit name    :  HELP_UTILITY         body
  1806. -- Author       :  Baskette
  1807. -- Date created :  28 January 1985
  1808. -- Last update  :
  1809. --                                                                    -*
  1810. ------------------------------------------------------------------------
  1811. --                                                                    -*
  1812. -- Abstract     : Body for the HELP Utility
  1813. ----------------: Contains the data strucutures and procedures used in the
  1814. ----------------: help utility other than those in the support package.
  1815. --                                                                    -*
  1816. ------------------------------------------------------------------------
  1817. --
  1818. -- Mnemonic     :
  1819. -- Name         :
  1820. -- Release date :
  1821. ------------------ Revision history ------------------------------------
  1822. --
  1823. -- DATE  AUTHOR   HISTORY
  1824. --
  1825. --
  1826. --
  1827. --------------------END-PROLOGUE----------------------------------------
  1828.  
  1829. with TEXT_IO;
  1830. with HELP_INFO_SUPPORT;
  1831. use HELP_INFO_SUPPORT;
  1832.  
  1833. package body HELP_UTILITY is
  1834.  
  1835. -- Text File for Help Utility
  1836.  
  1837.     HELP_FILE_TYPE: text_io.file_type;
  1838.  
  1839. -- Tree Data Structures
  1840.  
  1841.     type HELP_TOPIC;
  1842.     type HELP_LINK  is access HELP_TOPIC;
  1843.     type HELP_TOPIC is
  1844.         record
  1845.             NAME             : FILE_TEXT_LINE;
  1846.             NAME_LENGTH      : positive := 1;
  1847.             LEVEL            : natural := 1;
  1848.             TEXT_LINES       : HELP_INFO_SUPPORT.TEXT_LINK := null;
  1849.             SUBTOPICS        : HELP_LINK := null; -- link to first subtopic
  1850.             PARENT           : HELP_LINK := null; -- link to parent record
  1851.             NEXT_TOPIC       : HELP_LINK := null; -- link to next on same level
  1852.         end record;
  1853.  
  1854. -- other common needs
  1855.  
  1856.     TOP_NODE     : HELP_LINK := new HELP_TOPIC;
  1857.     CURRENT_NODE: HELP_LINK := null;
  1858.  
  1859.     OUTPUT_LINE: HELP_INFO_SUPPORT.HELP_INFO_TEXT_LINE;
  1860.     BLANK_LINE : HELP_INFO_TEXT_LINE :=
  1861.                          (1..HELP_INFO_SUPPORT.MAX_LINE_LENGTH =>' ');
  1862.     HEADER_LINE: constant string := "Information Available:";
  1863.     ADD_HEADER_LINE: constant string := "Additional Information Available:";
  1864.     TERM_LINE: constant string := "Help Terminated";
  1865.     TOPIC_LINE: constant string := "topic? ";
  1866.     SUBTOPIC_LINE: constant string := "subtopic? ";
  1867.     NO_DOC_LINE: constant string := "Sorry, no documentation available on ";
  1868.  
  1869.     HELP_MODE: boolean := false;
  1870.     FIRST_HELP_ME_CALL: boolean := true;
  1871.     INITIALIZED: boolean := false;
  1872.  
  1873. -- Procedures
  1874.  
  1875.     procedure INITIALIZE(HELP_FILE_NAME: in string)
  1876.            is separate;
  1877.  
  1878.     procedure FIND_KEYWORD(NODE_NAME: in string;
  1879.                            NODE_NAME_LENGTH: in natural;
  1880.                            NODE: in HELP_LINK;
  1881.                            KEYWORD_MATCHES: out HELP_LINK;
  1882.                            MATCH_COUNT: in out natural)
  1883.            is separate;
  1884.  
  1885.     procedure PRINT_TOPIC_MENU(NODE: in HELP_LINK)
  1886.            is separate;
  1887.  
  1888.     procedure PRINT_TOPIC_TEXT(NODE: in HELP_LINK)
  1889.            is separate;
  1890.  
  1891.     procedure PRINT_CURRENT_PROMPT(NODE: in HELP_LINK)
  1892.            is separate;
  1893.  
  1894.     procedure DISPLAY_ALL_HELP_INFO(NODE: in HELP_LINK)
  1895.            is separate;
  1896.  
  1897.     procedure HELP_ME(CLI_BUFFER: in string)
  1898.            is separate;
  1899.  
  1900.     procedure GET_TEXT_LINE(LINE: out string;
  1901.                             CHAR_COUNT: out natural;
  1902.                             IS_LAST: out boolean)
  1903.            is separate;
  1904.  
  1905.     procedure EXIT_HELP
  1906.            is separate;
  1907.  
  1908.     procedure RESET_HELP
  1909.            is separate;
  1910.  
  1911.     function HELP_IS_TERMINATED return boolean is
  1912.     begin
  1913.       if HELP_MODE then
  1914.         return false;
  1915.       else
  1916.         return true;
  1917.       end if;
  1918.     end HELP_IS_TERMINATED;
  1919.  
  1920. end HELP_UTILITY;
  1921. ::::::::::
  1922. HELP_DIS_ALL.ADA
  1923. ::::::::::
  1924. -------------------------PROLOGUE---------------------------------------
  1925. --                                                                    -*
  1926. -- Unit name    :  DISPLAY_ALL_HELP_INFO
  1927. -- Date created :  28 January 1985
  1928. -- Last update  :
  1929. --                                                                    -*
  1930. ------------------------------------------------------------------------
  1931. --                                                                    -*
  1932. -- Abstract     :  This procedure prints all information under the
  1933. ----------------: given node including text and menu.
  1934. ----------------: It traverses the tree using recursion.
  1935. --                                                                    -*
  1936. ------------------------------------------------------------------------
  1937. --
  1938. -- Mnemonic     :
  1939. -- Name         :
  1940. -- Release date :
  1941. ------------------ Revision history ------------------------------------
  1942. --
  1943. -- DATE  AUTHOR   HISTORY
  1944. --
  1945. --
  1946. --
  1947. --------------------END-PROLOGUE----------------------------------------
  1948.  
  1949.  
  1950. separate(HELP_UTILITY)
  1951. procedure DISPLAY_ALL_HELP_INFO(NODE: in HELP_UTILITY.HELP_LINK) is
  1952.  
  1953. BLANK_LINE_LENGTH: constant natural := 0;
  1954.  
  1955. begin
  1956.  
  1957. HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  1958.                                     BLANK_LINE_LENGTH);
  1959. HELP_UTILITY.OUTPUT_LINE := HELP_UTILITY.BLANK_LINE;
  1960. HELP_UTILITY.OUTPUT_LINE(1..NODE.NAME_LENGTH) := NODE.NAME(1..NODE.NAME_LENGTH);
  1961. HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.OUTPUT_LINE,
  1962.                                     NODE.NAME_LENGTH);
  1963. HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  1964.                                     BLANK_LINE_LENGTH);
  1965. HELP_UTILITY.PRINT_TOPIC_TEXT(NODE);
  1966.  
  1967. if NODE.SUBTOPICS /= null then
  1968.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  1969.                                     BLANK_LINE_LENGTH);
  1970.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.ADD_HEADER_LINE,
  1971.                                     HELP_UTILITY.ADD_HEADER_LINE'length);
  1972.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  1973.                                     BLANK_LINE_LENGTH);
  1974.   HELP_UTILITY.PRINT_TOPIC_MENU(NODE);
  1975. end if;
  1976.  
  1977. -- go down subtopics link first
  1978.  
  1979. if NODE.SUBTOPICS /= null then
  1980.   DISPLAY_ALL_HELP_INFO(NODE.SUBTOPICS);
  1981. end if;
  1982.  
  1983. -- go down next topic link last
  1984.  
  1985. if NODE.NEXT_TOPIC /= null then
  1986.   DISPLAY_ALL_HELP_INFO(NODE.NEXT_TOPIC);
  1987. end if;
  1988.  
  1989. end DISPLAY_ALL_HELP_INFO;
  1990. ::::::::::
  1991. HELP_EXIT.ADA
  1992. ::::::::::
  1993. -------------------------PROLOGUE---------------------------------------
  1994. --                                                                    -*
  1995. -- Unit name    :  EXIT_HELP
  1996. -- Date created :  28 January 1985
  1997. -- Last update  :
  1998. --                                                                    -*
  1999. ------------------------------------------------------------------------
  2000. --                                                                    -*
  2001. -- Abstract     :  The procedure sets the help mode flag to false and
  2002. ----------------: resets the current node pointer to the top node of the
  2003. ----------------: tree.
  2004. --                                                                    -*
  2005. ------------------------------------------------------------------------
  2006. --
  2007. -- Mnemonic     :
  2008. -- Name         :
  2009. -- Release date :
  2010. ------------------ Revision history ------------------------------------
  2011. --
  2012. -- DATE  AUTHOR   HISTORY
  2013. --
  2014. --
  2015. --
  2016. --------------------END-PROLOGUE----------------------------------------
  2017.  
  2018.  
  2019. separate (HELP_UTILITY)
  2020. procedure EXIT_HELP is
  2021.  
  2022. begin
  2023.  
  2024. HELP_UTILITY.CURRENT_NODE := HELP_UTILITY.TOP_NODE;
  2025.  
  2026. -- reset HELP_MODE to off
  2027.  
  2028. HELP_UTILITY.HELP_MODE := false;
  2029. HELP_UTILITY.FIRST_HELP_ME_CALL := TRUE;
  2030.  
  2031. end EXIT_HELP;
  2032. ::::::::::
  2033. HELP_FIND.ADA
  2034. ::::::::::
  2035. -------------------------PROLOGUE---------------------------------------
  2036. --                                                                    -*
  2037. -- Unit name    :  FIND_KEYWORD
  2038. -- Date created :  28 January 1985
  2039. -- Last update  :
  2040. --                                                                    -*
  2041. ------------------------------------------------------------------------
  2042. --                                                                    -*
  2043. -- Abstract     : This procedure will return a node (list of nodes) that
  2044. ----------------: potentially matches the given name. A count is returned
  2045. ----------------: of the number of matches.
  2046. --                                                                    -*
  2047. ------------------------------------------------------------------------
  2048. --
  2049. -- Mnemonic     :
  2050. -- Name         :
  2051. -- Release date :
  2052. ------------------ Revision history ------------------------------------
  2053. --
  2054. -- DATE  AUTHOR   HISTORY
  2055. --
  2056. --
  2057. --
  2058. --------------------END-PROLOGUE----------------------------------------
  2059.  
  2060.  
  2061. separate (HELP_UTILITY)
  2062. procedure FIND_KEYWORD (NODE_NAME: in string;
  2063.                         NODE_NAME_LENGTH: in natural;
  2064.                         NODE: in HELP_UTILITY.HELP_LINK;
  2065.                         KEYWORD_MATCHES: out HELP_UTILITY.HELP_LINK;
  2066.                         MATCH_COUNT: in out natural) is
  2067.  
  2068. KEYWORD_NODE: HELP_UTILITY.HELP_LINK := null;
  2069. PREV_NODE: HELP_UTILITY.HELP_LINK := null;
  2070. CURR_NODE: HELP_UTILITY.HELP_LINK := null;
  2071. TOP: HELP_UTILITY.HELP_LINK := CURR_NODE;
  2072.  
  2073. begin
  2074.  
  2075. KEYWORD_NODE := NODE.SUBTOPICS;
  2076. MATCH_COUNT := 0;
  2077.  
  2078. -- loop through all subtopics of current level and save any potential matches
  2079.  
  2080. while KEYWORD_NODE /= null loop
  2081.  begin
  2082.  
  2083. -- make the procedure call with input and subtopic name
  2084.  
  2085.   HELP_INFO_SUPPORT.IDENTIFY_KEYWORD(
  2086.               NODE_NAME,
  2087.               NODE_NAME_LENGTH,
  2088.               KEYWORD_NODE.NAME);
  2089.  
  2090. -- if a match is found, control returns to here, else exception is raised
  2091. -- save the match (could be partial match)
  2092.  
  2093.   CURR_NODE := new HELP_UTILITY.HELP_TOPIC;
  2094.   CURR_NODE.all := KEYWORD_NODE.all;
  2095.  
  2096.   if PREV_NODE = null then
  2097.     TOP := CURR_NODE;
  2098.   else
  2099.     PREV_NODE.NEXT_TOPIC := CURR_NODE;
  2100.   end if;
  2101.  
  2102.   PREV_NODE := CURR_NODE;
  2103.   MATCH_COUNT := MATCH_COUNT + 1;
  2104.  
  2105. -- if a match is not made then exception is raised
  2106.  
  2107.   exception
  2108.     when KEYWORD_NOT_FOUND => null;
  2109.  end;
  2110.  
  2111.  KEYWORD_NODE := KEYWORD_NODE.NEXT_TOPIC;
  2112. end loop;
  2113.  
  2114. KEYWORD_MATCHES := TOP;
  2115.  
  2116. -- other exceptions handled here
  2117.  
  2118.   exception
  2119.     when others => raise;
  2120. end FIND_KEYWORD;
  2121. ::::::::::
  2122. HELP_GET.ADA
  2123. ::::::::::
  2124. -------------------------PROLOGUE---------------------------------------
  2125. --                                                                    -*
  2126. -- Unit name    :  GET_TEXT_LINE
  2127. -- Date created :  20 Febrauary 1985
  2128. -- Last update  :
  2129. --                                                                    -*
  2130. ------------------------------------------------------------------------
  2131. --                                                                    -*
  2132. -- Abstract     : This procedure allows the user of the HELP_UTILITY
  2133. --              : to print the data accumulated by HELP_ME;
  2134. --                                                                    -*
  2135. ------------------------------------------------------------------------
  2136. --
  2137. -- Mnemonic     :
  2138. -- Name         :
  2139. -- Release date :
  2140. ------------------ Revision history ------------------------------------
  2141. --
  2142. -- DATE  AUTHOR   HISTORY
  2143. --
  2144. --
  2145. --
  2146. --------------------END-PROLOGUE----------------------------------------
  2147.  
  2148.  
  2149. separate (HELP_UTILITY)
  2150. procedure GET_TEXT_LINE (LINE: out string;
  2151.                          CHAR_COUNT: out natural;
  2152.                          IS_LAST: out boolean) is
  2153.  
  2154. IS_LAST_TIME: boolean := false;
  2155. LAST_CHAR_POS: natural := 0;
  2156.  
  2157. begin
  2158.  
  2159. IS_LAST := false;
  2160.  
  2161. if HELP_INFO_SUPPORT.TOP_LINE = null then
  2162.   raise HELP_UTILITY.NOTHING_TO_OUTPUT;
  2163.  
  2164. else
  2165.   if HELP_INFO_SUPPORT.IS_FIRST_TIME then
  2166.     HELP_INFO_SUPPORT.CURRENT_LINE := HELP_INFO_SUPPORT.TOP_LINE;
  2167.     HELP_INFO_SUPPORT.IS_FIRST_TIME := false;
  2168.   end if;
  2169.  
  2170.   if LINE'length > HELP_INFO_SUPPORT.CURRENT_LINE.LINE_LENGTH then
  2171.     LINE := (1..LINE'length => ' ');
  2172.     LINE(1..HELP_INFO_SUPPORT.CURRENT_LINE.LINE_LENGTH)
  2173.                            := HELP_INFO_SUPPORT.CURRENT_LINE.
  2174.              TEXT_LINE(1..HELP_INFO_SUPPORT.CURRENT_LINE.LINE_LENGTH);
  2175.     CHAR_COUNT := HELP_INFO_SUPPORT.CURRENT_LINE.LINE_LENGTH;
  2176.   else
  2177.     LINE := HELP_INFO_SUPPORT.CURRENT_LINE.TEXT_LINE
  2178.                          (1..LINE'length);
  2179.     CHAR_COUNT := LINE'length;
  2180.   end if;
  2181.  
  2182.   if HELP_INFO_SUPPORT.CURRENT_LINE.NEXT_LINE = null then
  2183.      HELP_INFO_SUPPORT.CURRENT_LINE := HELP_INFO_SUPPORT.TOP_LINE;
  2184.      IS_LAST := true;
  2185.      IS_LAST_TIME := true;
  2186.  
  2187.   else
  2188.     HELP_INFO_SUPPORT.CURRENT_LINE :=
  2189.                     HELP_INFO_SUPPORT.CURRENT_LINE.NEXT_LINE;
  2190.   end if;
  2191. end if;
  2192.  
  2193. if IS_LAST_TIME then
  2194.   HELP_INFO_SUPPORT.CURRENT_LINE := HELP_INFO_SUPPORT.TOP_LINE;
  2195.   HELP_INFO_SUPPORT.PREVIOUS_LINE := HELP_INFO_SUPPORT.TOP_LINE;
  2196.   HELP_INFO_SUPPORT.IS_FIRST_TIME := true;
  2197. end if;
  2198.  
  2199. exception
  2200.     when HELP_UTILITY.NOTHING_TO_OUTPUT => raise;
  2201.  
  2202.     when others => raise;
  2203. end GET_TEXT_LINE;
  2204. ::::::::::
  2205. HELP_INIT.ADA
  2206. ::::::::::
  2207. -------------------------PROLOGUE---------------------------------------
  2208. --                                                                    -*
  2209. -- Unit name    :  INITIALIZE
  2210. -- Date created :  28 January 1985
  2211. -- Last update  :
  2212. --                                                                    -*
  2213. ------------------------------------------------------------------------
  2214. --                                                                    -*
  2215. -- Abstract     :  This procedure reads in the specified help file into a
  2216. ----------------: data structure (linked list). Comments are ignored. Any
  2217. ----------------: input line starting with a digit is considered a new
  2218. ----------------: level. All other lines are considered text lines.
  2219. --                                                                    -*
  2220. ------------------------------------------------------------------------
  2221. --
  2222. -- Mnemonic     :
  2223. -- Name         :
  2224. -- Release date :
  2225. ------------------ Revision history ------------------------------------
  2226. --
  2227. -- DATE  AUTHOR   HISTORY
  2228. --
  2229. --
  2230. --
  2231. --------------------END-PROLOGUE----------------------------------------
  2232.  
  2233.  
  2234. separate (HELP_UTILITY)
  2235. procedure INITIALIZE(HELP_FILE_NAME: in string) is
  2236.  
  2237.     PREVIOUS_NODE             : HELP_UTILITY.HELP_LINK := TOP_NODE;
  2238.     PREVIOUS_LINE             : HELP_INFO_SUPPORT.TEXT_LINK := null;
  2239.     CURRENT_LINE              : HELP_INFO_SUPPORT.TEXT_LINK := null;
  2240.     CURRENT_LEVEL             : integer := 1;        -- current topic level
  2241.     TOKEN_IS_DIGITS           : boolean := false;  -- indicates if new record
  2242.     FIRST_DIGIT_FOUND         : boolean := false; -- topic must be before text
  2243.     LINE_BUFFER               : HELP_INFO_SUPPORT.FILE_TEXT_LINE;
  2244.     LAST                      : natural := 0; -- # of characters in LINE_BUFFER
  2245.     FIRST_TEXT_CHAR           : natural := 0; -- first non-digit character
  2246.  
  2247. -- exception
  2248.  
  2249.     TEXT_FILE_LEVEL_BAD       : exception;
  2250.     TEXT_BEFORE_TOPIC         : exception;
  2251.  
  2252. begin
  2253.  
  2254.     HELP_UTILITY.HELP_MODE := true;
  2255.     HELP_UTILITY.FIRST_HELP_ME_CALL := true;
  2256.  
  2257.     text_io.open (HELP_UTILITY.HELP_FILE_TYPE,   -- open the help file
  2258.                   text_io.in_file,
  2259.                   HELP_FILE_NAME,
  2260.                   "");
  2261.  
  2262.     while not text_io.end_of_file (HELP_UTILITY.HELP_FILE_TYPE) loop
  2263.  
  2264. --    blank the input buffer before using
  2265.  
  2266.       LINE_BUFFER := HELP_UTILITY.BLANK_LINE;
  2267.  
  2268.       text_io.get_line (HELP_UTILITY.HELP_FILE_TYPE, LINE_BUFFER, LAST);
  2269.  
  2270. --    Check if comment input. If so, skip the record.
  2271.  
  2272.       if LINE_BUFFER(LINE_BUFFER'first) = '-' and then
  2273.             LINE_BUFFER(LINE_BUFFER'first+1) = '-' then
  2274.             null;  -- comment read, ignore it
  2275.  
  2276.       else
  2277.  
  2278. --      Check if new topic read, i.e., digit is first character of record.
  2279.  
  2280.         if LINE_BUFFER (LINE_BUFFER'first) in '0' .. '9' then
  2281.             TOKEN_IS_DIGITS := true;
  2282.             FIRST_DIGIT_FOUND := true;
  2283.             FIRST_TEXT_CHAR := 1;
  2284.  
  2285. --        loop until all digits found
  2286.  
  2287.           while LINE_BUFFER(FIRST_TEXT_CHAR) in '0' .. '9' and
  2288.                   FIRST_TEXT_CHAR < HELP_INFO_SUPPORT.MAX_LINE_LENGTH loop
  2289.  
  2290.               FIRST_TEXT_CHAR := FIRST_TEXT_CHAR + 1;
  2291.           end loop;
  2292.  
  2293. --        convert to integer value
  2294.  
  2295.           CURRENT_LEVEL := integer'value(LINE_BUFFER
  2296.                              (LINE_BUFFER'first .. FIRST_TEXT_CHAR - 1)) -
  2297.                              integer'value ("0");
  2298.  
  2299. --        skip any blanks between level and keyword
  2300.  
  2301.           while LINE_BUFFER(FIRST_TEXT_CHAR) = ' ' loop
  2302.             FIRST_TEXT_CHAR := FIRST_TEXT_CHAR + 1;
  2303.           end loop;
  2304.         end if;
  2305.  
  2306.         if TOKEN_IS_DIGITS then
  2307.  
  2308. -- NEW TOPIC:
  2309. --          Tree structure note: SUBTOPICS links are for children
  2310. --                               NEXT_TOPIC links are for siblings
  2311. --                               TOP_NODE is the Papa/Mama node
  2312. --     Three cases:
  2313. --     1) Current topic level is greater than previous topic level
  2314. --          (current is subtopic of previous)
  2315. --     2) Current topic level is less than previous topic level
  2316. --     3) Current topic level is same as previous (or default when first)
  2317.  
  2318.           PREVIOUS_LINE := null;
  2319.           HELP_UTILITY.CURRENT_NODE := new HELP_UTILITY.HELP_TOPIC ;
  2320.  
  2321.           if CURRENT_LEVEL > PREVIOUS_NODE.LEVEL then
  2322.  
  2323. --  CASE 1: Current topic level is greater than previous topic level
  2324. --          Set double links
  2325.  
  2326. --          check that level increases by only one
  2327.  
  2328.             if CURRENT_LEVEL - PREVIOUS_NODE.LEVEL > 1 then
  2329.               raise TEXT_FILE_LEVEL_BAD;
  2330.             end if;
  2331.  
  2332.             PREVIOUS_NODE.SUBTOPICS := HELP_UTILITY.CURRENT_NODE;
  2333.             HELP_UTILITY.CURRENT_NODE.PARENT := PREVIOUS_NODE;
  2334.  
  2335.           elsif CURRENT_LEVEL < PREVIOUS_NODE.LEVEL then
  2336.  
  2337. -- CASE 2: Current topic level is less than previous topic level
  2338. --         Go back up tree to same level as current.
  2339.  
  2340.             while CURRENT_LEVEL < PREVIOUS_NODE.LEVEL loop
  2341.                     PREVIOUS_NODE := PREVIOUS_NODE.PARENT;
  2342.             end loop;
  2343.  
  2344.             PREVIOUS_NODE.NEXT_TOPIC := HELP_UTILITY.CURRENT_NODE;
  2345.             HELP_UTILITY.CURRENT_NODE.PARENT := PREVIOUS_NODE;
  2346.  
  2347. -- CASE 3: Level has not changed.
  2348.  
  2349.           else
  2350.  
  2351. --          initial case only. Link off of TOP_NODE's subtopic link
  2352.  
  2353.             if PREVIOUS_NODE = HELP_UTILITY.TOP_NODE then
  2354.               PREVIOUS_NODE.SUBTOPICS := HELP_UTILITY.CURRENT_NODE;
  2355.               HELP_UTILITY.CURRENT_NODE.PARENT := PREVIOUS_NODE;
  2356.  
  2357. --          all other cases when same level, link to next_topic.
  2358.  
  2359.             else
  2360.               PREVIOUS_NODE.NEXT_TOPIC := HELP_UTILITY.CURRENT_NODE;
  2361.               HELP_UTILITY.CURRENT_NODE.PARENT := PREVIOUS_NODE;
  2362.             end if;
  2363.           end if;
  2364.  
  2365. --        Save the topics name, name length, and level
  2366.  
  2367.           HELP_UTILITY.CURRENT_NODE.NAME(
  2368.               1..HELP_INFO_SUPPORT.FILE_TEXT_LINE'last)
  2369.                  := LINE_BUFFER (FIRST_TEXT_CHAR .. LAST) &
  2370.                      (LAST - FIRST_TEXT_CHAR +
  2371.                         2..HELP_INFO_SUPPORT.FILE_TEXT_LINE'last => ' ');
  2372.           HELP_UTILITY.CURRENT_NODE.NAME_LENGTH := LAST - FIRST_TEXT_CHAR + 1;
  2373.           HELP_UTILITY.CURRENT_NODE.LEVEL := CURRENT_LEVEL;
  2374.  
  2375. --        update previous to current and go get next
  2376.  
  2377.           PREVIOUS_NODE := HELP_UTILITY.CURRENT_NODE;
  2378.  
  2379. -- TEXT INPUT
  2380. --      Add text to buffer
  2381.  
  2382.         elsif FIRST_DIGIT_FOUND then
  2383.  
  2384. --        get a new blank line pointer
  2385.  
  2386.           CURRENT_LINE := new HELP_INFO_SUPPORT.TEXT_LINE;
  2387.  
  2388. --        save the text
  2389.  
  2390.           CURRENT_LINE.TEXT_LINE :=
  2391.                   LINE_BUFFER(1..LAST) &
  2392.                       (LAST+1 .. HELP_INFO_SUPPORT.FILE_TEXT_LINE'last => ' ');
  2393.  
  2394. --        save the length
  2395.  
  2396.           if LAST = natural'first then
  2397.             CURRENT_LINE.LINE_LENGTH := LAST + 1;
  2398.           else
  2399.             CURRENT_LINE.LINE_LENGTH := LAST;
  2400.           end if;
  2401.  
  2402. --        update pointers. First time, link to node, otherwise link to previous
  2403.  
  2404.           if PREVIOUS_LINE = null then
  2405.              HELP_UTILITY.CURRENT_NODE.TEXT_LINES := CURRENT_LINE;
  2406.           else
  2407.              PREVIOUS_LINE.NEXT_LINE := CURRENT_LINE;
  2408.           end if;
  2409.  
  2410. --        update the previous line
  2411.  
  2412.           PREVIOUS_LINE := CURRENT_LINE;
  2413.  
  2414.         else
  2415.           raise TEXT_BEFORE_TOPIC;
  2416.  
  2417.         end if;
  2418.  
  2419. --       reset flag. Loop back for next
  2420.  
  2421.         TOKEN_IS_DIGITS := false;                  -- reset flag
  2422.       end if;
  2423.     end loop;
  2424.  
  2425.     text_io.close (HELP_UTILITY.HELP_FILE_TYPE);
  2426.  
  2427. --  set top node to a level of zero. This denotes the top
  2428.  
  2429.     HELP_UTILITY.TOP_NODE.LEVEL := 0;
  2430.     HELP_UTILITY.CURRENT_NODE := TOP_NODE;
  2431.     HELP_UTILITY.INITIALIZED := true;
  2432.  
  2433. exception
  2434.     when TEXT_FILE_LEVEL_BAD | TEXT_BEFORE_TOPIC =>
  2435.          raise HELP_UTILITY.ILLEGAL_FORMAT_FOR_HELP_FILE;
  2436.  
  2437.     when text_io.name_error =>
  2438.          raise HELP_UTILITY.HELP_FILE_DOES_NOT_EXIST;
  2439.  
  2440.     when text_io.status_error | text_io.use_error =>
  2441.          raise HELP_UTILITY.CANNOT_OPEN_HELP_FILE;
  2442.  
  2443.     when others => raise;
  2444. end INITIALIZE;
  2445. ::::::::::
  2446. HELP_ME.ADA
  2447. ::::::::::
  2448. -------------------------PROLOGUE---------------------------------------
  2449. --                                                                    -*
  2450. -- Unit name    :  HELP_ME
  2451. -- Date created :  28 January 1985
  2452. -- Last update  :
  2453. --                                                                    -*
  2454. ------------------------------------------------------------------------
  2455. --                                                                    -*
  2456. -- Abstract     :  This is procedure is the driver of the Help utility.
  2457. ----------------: It accepts the input from the CLI and determines the
  2458. ----------------: appropriate action to take.
  2459. --                                                                    -*
  2460. ------------------------------------------------------------------------
  2461. --
  2462. -- Mnemonic     :
  2463. -- Name         :
  2464. -- Release date :
  2465. ------------------ Revision history ------------------------------------
  2466. --
  2467. -- DATE  AUTHOR   HISTORY
  2468. --
  2469. --
  2470. --
  2471. --------------------END-PROLOGUE----------------------------------------
  2472.  
  2473.  
  2474. separate (HELP_UTILITY)
  2475. procedure HELP_ME(CLI_BUFFER: in string) is
  2476.  
  2477. TOKEN_COUNT: positive := 1; -- number of tokens in input string
  2478. MATCH_COUNT: natural := 0; -- number of token matches at current level
  2479. COUNTER: natural := 0; -- loop control
  2480. KEYWORD_MATCHES: HELP_UTILITY.HELP_LINK := null; -- list of nodes that match
  2481. TOP_SAVE: HELP_UTILITY.HELP_LINK := null; -- first node of KEYWORD_MATCHES
  2482. SAME_LEVEL: natural := 0; -- copy of current level of node
  2483. MSG_NAME: HELP_INFO_SUPPORT.HELP_INFO_TEXT_LINE;
  2484. BLANK_LINE_LENGTH: constant natural := 0;
  2485. TEMP_NODE: HELP_UTILITY.HELP_LINK := new HELP_UTILITY.HELP_TOPIC;
  2486. OUT_LINE_LENGTH:  natural := 0;
  2487.  
  2488. -- exceptions
  2489.  
  2490. HELP_FILE_NOT_READ: exception;
  2491.  
  2492. begin
  2493.  
  2494. if not HELP_UTILITY.INITIALIZED then
  2495.   raise HELP_FILE_NOT_READ;
  2496. end if;
  2497.  
  2498. if HELP_UTILITY.HELP_MODE then
  2499.  
  2500. -- parse the input string. A table of tokens is returned
  2501.  
  2502. HELP_INFO_SUPPORT.PARSE(CLI_BUFFER);
  2503.  
  2504. -- if no tokens, a carriage return was entered. move up a level
  2505.  
  2506. if HELP_INFO_SUPPORT.NUMBER_OF_TOKENS = 0 then
  2507.  
  2508. -- if this is the first time help is entered and no topic is specified,
  2509. --    output the first level memu
  2510.  
  2511.   if HELP_UTILITY.FIRST_HELP_ME_CALL then
  2512.     HELP_UTILITY.OUTPUT_LINE := HELP_UTILITY.BLANK_LINE;
  2513.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2514.                         BLANK_LINE_LENGTH);
  2515.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.HEADER_LINE,
  2516.                         HELP_UTILITY.HEADER_LINE'length);
  2517.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2518.                         BLANK_LINE_LENGTH);
  2519.     HELP_UTILITY.PRINT_TOPIC_MENU(CURRENT_NODE);
  2520.  
  2521. -- else, if at the upper most level and a carriage return is entered, set
  2522. --       terminate to true.
  2523.  
  2524.   else
  2525.     if HELP_UTILITY.CURRENT_NODE = HELP_UTILITY.TOP_NODE then
  2526.       HELP_UTILITY.EXIT_HELP;
  2527.  
  2528.     else
  2529.  
  2530. --    not at top level. back up one level (until level changes)
  2531.  
  2532.       SAME_LEVEL := HELP_UTILITY.CURRENT_NODE.LEVEL;
  2533.  
  2534.       while HELP_UTILITY.CURRENT_NODE.LEVEL = SAME_LEVEL loop
  2535.         HELP_UTILITY.CURRENT_NODE := HELP_UTILITY.CURRENT_NODE.PARENT;
  2536.       end loop;
  2537.     end if;
  2538.   end if;
  2539.  
  2540. else
  2541.  
  2542. --  loop through the token table returned from PARSE until either:
  2543. --       1) "*" found,
  2544. --       2) "?" found,
  2545. --       3) more than one match is found at a level or
  2546. --       4) tokens are exhausted
  2547.  
  2548.   loop
  2549.     if HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).TOKEN(1..
  2550.           HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH) = "*"  or
  2551.           HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).TOKEN(1..
  2552.           HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH) = "?" then
  2553.       exit;
  2554.     end if;
  2555.  
  2556.     FIND_KEYWORD(HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).TOKEN,
  2557.                HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH,
  2558.                HELP_UTILITY.CURRENT_NODE,
  2559.                KEYWORD_MATCHES,
  2560.                MATCH_COUNT);
  2561.  
  2562. --  if more than one (ambiguous input) or no match is found, then ignore the
  2563. --     remaining tokens, exit loop
  2564.  
  2565.     if MATCH_COUNT /= 1 then
  2566.       exit;
  2567.     end if;
  2568.  
  2569. --  if all tokens checked, exit loop
  2570.  
  2571.     if TOKEN_COUNT = HELP_INFO_SUPPORT.NUMBER_OF_TOKENS then
  2572.       exit;
  2573.  
  2574.     else
  2575.  
  2576. --  increment the counter and update the current node to the match found
  2577.  
  2578.       TOKEN_COUNT := TOKEN_COUNT + 1;
  2579.       HELP_UTILITY.CURRENT_NODE := KEYWORD_MATCHES;
  2580.     end if;
  2581.   end loop;
  2582.  
  2583. -- check if all info from current level on down is requested
  2584.  
  2585.   if HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).TOKEN(1..
  2586.           HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH) = "*" then
  2587.  
  2588.       if CURRENT_NODE = TOP_NODE then
  2589.         TEMP_NODE.all := HELP_UTILITY.CURRENT_NODE.SUBTOPICS.all;
  2590.       else
  2591.         TEMP_NODE.all := HELP_UTILITY.CURRENT_NODE.all;
  2592.         TEMP_NODE.NEXT_TOPIC := null;
  2593.       end if;
  2594.  
  2595.       HELP_UTILITY.DISPLAY_ALL_HELP_INFO(TEMP_NODE);
  2596.  
  2597.       if HELP_UTILITY.CURRENT_NODE.SUBTOPICS = null then
  2598.         SAME_LEVEL := HELP_UTILITY.CURRENT_NODE.LEVEL;
  2599.  
  2600.         while HELP_UTILITY.CURRENT_NODE.LEVEL = SAME_LEVEL loop
  2601.           HELP_UTILITY.CURRENT_NODE := HELP_UTILITY.CURRENT_NODE.PARENT ;
  2602.         end loop;
  2603.       end if;
  2604.  
  2605. -- check if an implied help was requested, i.e., menu for current level
  2606.  
  2607.   elsif HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).TOKEN(1..
  2608.           HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH) = "?" then
  2609.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2610.                         BLANK_LINE_LENGTH);
  2611.     HELP_UTILITY.PRINT_TOPIC_TEXT(HELP_UTILITY.CURRENT_NODE);
  2612.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2613.                         BLANK_LINE_LENGTH);
  2614.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.ADD_HEADER_LINE,
  2615.                         HELP_UTILITY.ADD_HEADER_LINE'length);
  2616.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2617.                         BLANK_LINE_LENGTH);
  2618.     HELP_UTILITY.PRINT_TOPIC_MENU(HELP_UTILITY.CURRENT_NODE);
  2619.  
  2620. -- if a match(es) was found, output the info for that match(es)
  2621.  
  2622.   elsif MATCH_COUNT /= 0 then
  2623.     COUNTER := MATCH_COUNT;  -- counter will be used for loop control
  2624.     TOP_SAVE := KEYWORD_MATCHES; -- save the top for later restoration
  2625.  
  2626. --  this loop goes through the list (possibly only one) of matches found
  2627. --       above. KEYWORD_MATCHES is a linked list of the matches. Each
  2628. --       match has its text and menu of subtopics output
  2629.  
  2630.     while COUNTER /= 0 loop
  2631.       HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2632.                         BLANK_LINE_LENGTH);
  2633.       HELP_UTILITY.OUTPUT_LINE := HELP_UTILITY.BLANK_LINE;
  2634.       HELP_UTILITY.OUTPUT_LINE(1..KEYWORD_MATCHES.NAME_LENGTH) :=
  2635.                          KEYWORD_MATCHES.NAME(1..KEYWORD_MATCHES.NAME_LENGTH);
  2636.       HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.OUTPUT_LINE,
  2637.                         KEYWORD_MATCHES.NAME_LENGTH);
  2638.       HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2639.                         BLANK_LINE_LENGTH);
  2640.       HELP_UTILITY.PRINT_TOPIC_TEXT(KEYWORD_MATCHES);
  2641.  
  2642. --    check if any subtopics, i.e., if a menu should be output
  2643.  
  2644.       if KEYWORD_MATCHES.SUBTOPICS /= null then
  2645.         if TOKEN_COUNT < HELP_INFO_SUPPORT.NUMBER_OF_TOKENS then
  2646.  
  2647. --        this checks for the case where an ambiguous token was entered followed
  2648. --          by an "*". in this case, output all info for all the matches of the
  2649. --          ambiguous input
  2650.  
  2651.           if HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT + 1).TOKEN(1..
  2652.              HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT + 1).LENGTH) = "*"
  2653.              then
  2654.  
  2655.             HELP_UTILITY.DISPLAY_ALL_HELP_INFO(KEYWORD_MATCHES.SUBTOPICS);
  2656.           end if;
  2657.         else
  2658.           HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2659.                         BLANK_LINE_LENGTH);
  2660.           HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.ADD_HEADER_LINE,
  2661.                         HELP_UTILITY.ADD_HEADER_LINE'length);
  2662.           HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2663.                         BLANK_LINE_LENGTH);
  2664.           HELP_UTILITY.PRINT_TOPIC_MENU(KEYWORD_MATCHES);
  2665.         end if;
  2666.       end if;
  2667.  
  2668.       KEYWORD_MATCHES := KEYWORD_MATCHES.NEXT_TOPIC;
  2669.       COUNTER := COUNTER - 1;
  2670.     end loop;
  2671.  
  2672. --  restore the top of the list
  2673.  
  2674.     KEYWORD_MATCHES := TOP_SAVE;
  2675.  
  2676. --  now we must decide what the next prompt should be (and thus, what the
  2677. --      current node should be [or vice versa]).
  2678. --      this only matters if one and only one match was found. Else, the
  2679. --      current node did not change.
  2680.  
  2681.     if MATCH_COUNT = 1 then
  2682.  
  2683. --     if there are no subtopics, the prompt should be for the next higher
  2684. --        level.
  2685.  
  2686.       if KEYWORD_MATCHES.SUBTOPICS = null then
  2687.  
  2688. --        if already at the highest level, set current to top
  2689.  
  2690.         if KEYWORD_MATCHES.LEVEL <= 1 then
  2691.           HELP_UTILITY.CURRENT_NODE := HELP_UTILITY.TOP_NODE;
  2692.         else
  2693.  
  2694. --        else, move up the links until the level changes. That node will then
  2695. --              become the current level
  2696.  
  2697.           SAME_LEVEL := KEYWORD_MATCHES.LEVEL;
  2698.  
  2699.           while KEYWORD_MATCHES.LEVEL = SAME_LEVEL loop
  2700.             KEYWORD_MATCHES := KEYWORD_MATCHES.PARENT;
  2701.           end loop;
  2702.  
  2703.           HELP_UTILITY.CURRENT_NODE := KEYWORD_MATCHES;
  2704.         end if;
  2705.  
  2706.       else
  2707.  
  2708. --    if there are subtopics, the current node becomes the one found and
  2709. --       the user is prompted for subtopic input
  2710.  
  2711.         HELP_UTILITY.CURRENT_NODE := KEYWORD_MATCHES;
  2712.       end if;
  2713.     end if;
  2714.  
  2715.   else
  2716.  
  2717. --  if no match was found and not a special character (* or ?) then no info
  2718. --     for user input request
  2719.  
  2720.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2721.                         BLANK_LINE_LENGTH);
  2722.  
  2723.     if HELP_UTILITY.NO_DOC_LINE'length +
  2724.             HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH >=
  2725.                 HELP_INFO_SUPPORT.MAX_LINE_LENGTH then
  2726.       MSG_NAME(1..HELP_INFO_SUPPORT.MAX_LINE_LENGTH) :=
  2727.                  HELP_UTILITY.NO_DOC_LINE &
  2728.                  HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).TOKEN(1..
  2729.                  HELP_INFO_SUPPORT.MAX_LINE_LENGTH -
  2730.                  HELP_UTILITY.NO_DOC_LINE'length);
  2731.       OUT_LINE_LENGTH := HELP_INFO_SUPPORT.MAX_LINE_LENGTH;
  2732.  
  2733.     else
  2734.       MSG_NAME(1..HELP_INFO_SUPPORT.MAX_LINE_LENGTH) :=
  2735.                  HELP_UTILITY.NO_DOC_LINE &
  2736.                  HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).TOKEN(1..
  2737.                    HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH) &
  2738.                  (HELP_UTILITY.NO_DOC_LINE'length +
  2739.                   HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH + 1 ..
  2740.                   HELP_INFO_SUPPORT.HELP_INFO_TEXT_LINE'last => ' ');
  2741.       OUT_LINE_LENGTH := HELP_UTILITY.NO_DOC_LINE'length +
  2742.                   HELP_INFO_SUPPORT.INPUT_TOKEN_TABLE(TOKEN_COUNT).LENGTH;
  2743.     end if;
  2744.  
  2745.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(MSG_NAME, OUT_LINE_LENGTH);
  2746.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2747.                         BLANK_LINE_LENGTH);
  2748.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.ADD_HEADER_LINE,
  2749.                         HELP_UTILITY.ADD_HEADER_LINE'length);
  2750.     HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2751.                         BLANK_LINE_LENGTH);
  2752.  
  2753.     if HELP_UTILITY.CURRENT_NODE.LEVEL >= 1 then
  2754.       if TOKEN_COUNT > 1 and HELP_UTILITY.CURRENT_NODE.LEVEL /=
  2755.                            HELP_UTILITY.CURRENT_NODE.PARENT.LEVEL then
  2756.         HELP_UTILITY.CURRENT_NODE := HELP_UTILITY.CURRENT_NODE.PARENT;
  2757.       end if;
  2758.     end if;
  2759.  
  2760.     HELP_UTILITY.PRINT_TOPIC_MENU(HELP_UTILITY.CURRENT_NODE);
  2761.     TOKEN_COUNT := HELP_INFO_SUPPORT.NUMBER_OF_TOKENS;
  2762.   end if;
  2763. end if;
  2764.  
  2765. -- before outputting the prompt, check that help was not terminated
  2766.  
  2767. if HELP_UTILITY.HELP_MODE then
  2768.   HELP_UTILITY.PRINT_CURRENT_PROMPT(HELP_UTILITY.CURRENT_NODE);
  2769. end if;
  2770.  
  2771. -- indicate that HELP is active
  2772.  
  2773. HELP_UTILITY.FIRST_HELP_ME_CALL := false;
  2774.  
  2775. end if;
  2776.  
  2777. exception
  2778.   when HELP_FILE_NOT_READ =>
  2779.     raise HELP_UTILITY.HELP_FILE_NOT_INITIALIZED;
  2780.  
  2781.   when others => HELP_UTILITY.HELP_MODE := false;
  2782.                  raise;
  2783. end HELP_ME;
  2784. ::::::::::
  2785. HELP_MENU.ADA
  2786. ::::::::::
  2787. -------------------------PROLOGUE---------------------------------------
  2788. --                                                                    -*
  2789. -- Unit name    :  PRINT_TOPIC_MENU
  2790. -- Date created :  28 January 1985
  2791. -- Last update  :
  2792. --                                                                    -*
  2793. ------------------------------------------------------------------------
  2794. --                                                                    -*
  2795. -- Abstract     :  This procedure will print a list of subtopics (menu) for
  2796. ----------------: the given node (if any exist). The subtopics are listed
  2797. ----------------: in two columns.
  2798. --                                                                    -*
  2799. ------------------------------------------------------------------------
  2800. --
  2801. -- Mnemonic     :
  2802. -- Name         :
  2803. -- Release date :
  2804. ------------------ Revision history ------------------------------------
  2805. --
  2806. -- DATE  AUTHOR   HISTORY
  2807. --
  2808. --
  2809. --
  2810. --------------------END-PROLOGUE----------------------------------------
  2811.  
  2812.  
  2813. separate (HELP_UTILITY)
  2814. procedure PRINT_TOPIC_MENU (NODE: in HELP_UTILITY.HELP_LINK) is
  2815.  
  2816.     TOTAL_NUMBER_OF_TOPICS:   natural := 0;
  2817.     NUM_TOPICS_IN_COLUMN_ONE: positive := 1;
  2818.     TOPICS_IN_COLUMN_TWO:     boolean := false;
  2819.     COL_WIDTH: integer := (HELP_INFO_SUPPORT.MAX_LINE_LENGTH/2) - 1;
  2820.     RIGHT_COLUMN_START: integer := COL_WIDTH + 3;
  2821.     EVEN:                     boolean := false;
  2822.     CURRENT_NODE:             HELP_UTILITY.HELP_LINK := null;
  2823.     COL_ONE_NODE:             HELP_UTILITY.HELP_LINK := null;
  2824.     COL_TWO_NODE:             HELP_UTILITY.HELP_LINK := null;
  2825.  
  2826. begin
  2827.  
  2828. CURRENT_NODE := NODE.SUBTOPICS;
  2829.  
  2830. -- count the number of subtopics for this node
  2831.  
  2832. while CURRENT_NODE /= null loop
  2833.   TOTAL_NUMBER_OF_TOPICS := TOTAL_NUMBER_OF_TOPICS + 1;
  2834.   CURRENT_NODE:= CURRENT_NODE.NEXT_TOPIC;
  2835. end loop;
  2836.  
  2837. -- If there is more than one topic, then split the topics into two columns
  2838. -- Column one will have the first half and column two the second half.
  2839. -- If there are an odd number of topics, column one will have the odd number
  2840.  
  2841. if TOTAL_NUMBER_OF_TOPICS /= 0 then
  2842.   if TOTAL_NUMBER_OF_TOPICS >= 2 then
  2843.     TOPICS_IN_COLUMN_TWO := true;
  2844.     NUM_TOPICS_IN_COLUMN_ONE := TOTAL_NUMBER_OF_TOPICS / 2;
  2845.  
  2846. -- More than one topic, split the number
  2847. -- See if odd number. If so, increment the topic count so odd goes in 1st col.
  2848.  
  2849.     if TOTAL_NUMBER_OF_TOPICS /= (TOTAL_NUMBER_OF_TOPICS/2) * 2 then
  2850.       NUM_TOPICS_IN_COLUMN_ONE := NUM_TOPICS_IN_COLUMN_ONE + 1;
  2851.  
  2852.     else
  2853.       EVEN := true;
  2854.     end if;
  2855.   end if;
  2856.  
  2857. -- set the beginning node for each column
  2858.  
  2859.   COL_ONE_NODE := NODE.SUBTOPICS;
  2860.   CURRENT_NODE := NODE.SUBTOPICS;
  2861.  
  2862.   for I in 1..NUM_TOPICS_IN_COLUMN_ONE loop
  2863.     COL_TWO_NODE := CURRENT_NODE.NEXT_TOPIC;
  2864.     CURRENT_NODE := CURRENT_NODE.NEXT_TOPIC;
  2865.   end loop;
  2866.  
  2867.   if TOPICS_IN_COLUMN_TWO then
  2868.     while COL_TWO_NODE /= null loop
  2869.       HELP_UTILITY.OUTPUT_LINE :=
  2870.                  HELP_UTILITY.BLANK_LINE; -- blank the line buffer
  2871.  
  2872. -- Put first topic in left half of output line
  2873. --     if full name will not fit then truncate
  2874.  
  2875.       if COL_WIDTH > COL_ONE_NODE.NAME_LENGTH then
  2876.  
  2877. --      full name will fit
  2878.  
  2879.         HELP_UTILITY.OUTPUT_LINE(1..COL_ONE_NODE.NAME_LENGTH) :=
  2880.          COL_ONE_NODE.NAME(1..COL_ONE_NODE.NAME_LENGTH);
  2881.  
  2882.       else
  2883.  
  2884. --      truncate
  2885.  
  2886.         HELP_UTILITY.OUTPUT_LINE(1..COL_WIDTH) :=
  2887.          COL_ONE_NODE.NAME(1..COL_WIDTH);
  2888.       end if;
  2889.  
  2890. -- Put second topic in second half of output line
  2891. --     if full name will not fit then truncate
  2892.  
  2893.       if COL_WIDTH > COL_TWO_NODE.NAME_LENGTH then
  2894.  
  2895. --      full name will fit
  2896.  
  2897.         HELP_UTILITY.OUTPUT_LINE(RIGHT_COLUMN_START..RIGHT_COLUMN_START +
  2898.                COL_TWO_NODE.NAME_LENGTH - 1 ) :=
  2899.                 COL_TWO_NODE.NAME(1..COL_TWO_NODE.NAME_LENGTH);
  2900.         HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.OUTPUT_LINE,
  2901.                      RIGHT_COLUMN_START - 1 + COL_TWO_NODE.NAME_LENGTH);
  2902.  
  2903.       else
  2904.  
  2905. --      truncate
  2906.  
  2907.         HELP_UTILITY.OUTPUT_LINE(RIGHT_COLUMN_START..RIGHT_COLUMN_START +
  2908.                COL_WIDTH - 1) :=
  2909.                 COL_TWO_NODE.NAME(1..COL_WIDTH);
  2910.         HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.OUTPUT_LINE,
  2911.                      RIGHT_COLUMN_START - 1 + COL_WIDTH);
  2912.  
  2913.       end if;
  2914.  
  2915.       COL_ONE_NODE := COL_ONE_NODE.NEXT_TOPIC;
  2916.       COL_TWO_NODE := COL_TWO_NODE.NEXT_TOPIC;
  2917.     end loop;
  2918.   end if;
  2919.  
  2920.   if not EVEN then
  2921.  
  2922. -- Put the odd topic in the output buffer
  2923.  
  2924.     HELP_UTILITY.OUTPUT_LINE := HELP_UTILITY.BLANK_LINE;
  2925.  
  2926. --  check if name will fit on output line
  2927.  
  2928.     if HELP_INFO_SUPPORT.MAX_LINE_LENGTH > COL_ONE_NODE.NAME_LENGTH then
  2929.  
  2930. --    name fits
  2931.  
  2932.       HELP_UTILITY.OUTPUT_LINE(1..COL_ONE_NODE.NAME_LENGTH) :=
  2933.              COL_ONE_NODE.NAME(1..COL_ONE_NODE.NAME_LENGTH);
  2934.       HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.OUTPUT_LINE,
  2935.                                   COL_ONE_NODE.NAME_LENGTH);
  2936.  
  2937. --  truncate
  2938.  
  2939.     else
  2940.       HELP_UTILITY.OUTPUT_LINE(1..HELP_INFO_SUPPORT.MAX_LINE_LENGTH) :=
  2941.              COL_ONE_NODE.NAME(1..HELP_INFO_SUPPORT.MAX_LINE_LENGTH);
  2942.       HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.OUTPUT_LINE,
  2943.                                   HELP_INFO_SUPPORT.MAX_LINE_LENGTH);
  2944.     end if;
  2945.   end if;
  2946. end if;
  2947.  
  2948. exception
  2949.     when others =>  raise;
  2950.  
  2951. end PRINT_TOPIC_MENU;
  2952. ::::::::::
  2953. HELP_PROMPT.ADA
  2954. ::::::::::
  2955. -------------------------PROLOGUE---------------------------------------
  2956. --                                                                    -*
  2957. -- Unit name    :  PRINT_CURRENT_PROMPT
  2958. -- Date created :  28 January 1985
  2959. -- Last update  :
  2960. --                                                                    -*
  2961. ------------------------------------------------------------------------
  2962. --                                                                    -*
  2963. -- Abstract     :  This procedure determines the prompt and outputs it.
  2964. --                                                                    -*
  2965. ------------------------------------------------------------------------
  2966. --
  2967. -- Mnemonic     :
  2968. -- Name         :
  2969. -- Release date :
  2970. ------------------ Revision history ------------------------------------
  2971. --
  2972. -- DATE  AUTHOR   HISTORY
  2973. --
  2974. --
  2975. --
  2976. --------------------END-PROLOGUE----------------------------------------
  2977.  
  2978.  
  2979. separate(HELP_UTILITY)
  2980. procedure PRINT_CURRENT_PROMPT(NODE: in HELP_UTILITY.HELP_LINK) is
  2981.  
  2982. TEMP_NODE: HELP_UTILITY.HELP_LINK := null;
  2983. PROMPT_END: integer := 1; -- number of allowable characters for prompt
  2984. SAVE_CURRENT_LEVEL: integer := 0;  -- used in reverse tree traversal
  2985. PROMPT_NAME: HELP_INFO_SUPPORT.HELP_INFO_TEXT_LINE := HELP_UTILITY.BLANK_LINE;
  2986. BLANK_LINE_LENGTH: constant natural := 0;
  2987.  
  2988. begin
  2989.  
  2990. -- there are two types of prompts:
  2991. -- 1) "topic? "
  2992. -- 2) "subtopic? "
  2993.  
  2994. -- "topic? " is output when at the highest level (at the top node)
  2995.  
  2996. if NODE = HELP_UTILITY.TOP_NODE then
  2997.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  2998.                                       BLANK_LINE_LENGTH);
  2999.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.TOPIC_LINE,
  3000.                                       HELP_UTILITY.TOPIC_LINE'length);
  3001.  
  3002. else
  3003.  
  3004. -- when at a lower level output the topic name(s) followed by "subtopic? "
  3005.  
  3006.   TEMP_NODE := NODE;
  3007.   SAVE_CURRENT_LEVEL := NODE.LEVEL;
  3008.  
  3009. -- put the prompt "subtopic? " in the buffer
  3010.  
  3011.   PROMPT_NAME(1..HELP_UTILITY.SUBTOPIC_LINE'length) :=
  3012.              HELP_UTILITY.SUBTOPIC_LINE;
  3013.   PROMPT_END := HELP_INFO_SUPPORT.MAX_LINE_LENGTH -
  3014.                      HELP_UTILITY.SUBTOPIC_LINE'length - 1;
  3015.  
  3016. -- now put the name of the current node in the buffer before the prompt
  3017.  
  3018.   PROMPT_NAME(1..TEMP_NODE.NAME_LENGTH +
  3019.          HELP_INFO_SUPPORT.MAX_LINE_LENGTH - PROMPT_END + 1) :=
  3020.               TEMP_NODE.NAME(1..TEMP_NODE.NAME_LENGTH) & ' ' &
  3021.                    PROMPT_NAME(1..HELP_INFO_SUPPORT.MAX_LINE_LENGTH -
  3022.                           PROMPT_END);
  3023.  
  3024.   PROMPT_END := PROMPT_END - TEMP_NODE.NAME_LENGTH - 1;
  3025.  
  3026. -- do a reverse tree traversal starting at the current node. if a level
  3027. --  changes, put that node's name in the output string
  3028.  
  3029.   while TEMP_NODE.LEVEL > 0 loop
  3030.     if SAVE_CURRENT_LEVEL /= TEMP_NODE.LEVEL then
  3031.       SAVE_CURRENT_LEVEL := TEMP_NODE.LEVEL;
  3032.  
  3033.       if SAVE_CURRENT_LEVEL > 0 then
  3034.  
  3035. --      if the name will not fit then exit and go with what we have
  3036.  
  3037.         if TEMP_NODE.NAME_LENGTH + 1 > PROMPT_END then
  3038.           exit;
  3039.         end if;
  3040.  
  3041.         PROMPT_NAME(1..TEMP_NODE.NAME_LENGTH +
  3042.                HELP_INFO_SUPPORT.MAX_LINE_LENGTH - PROMPT_END + 1) :=
  3043.                     TEMP_NODE.NAME(1..TEMP_NODE.NAME_LENGTH) & ' ' &
  3044.                     PROMPT_NAME(1..HELP_INFO_SUPPORT.MAX_LINE_LENGTH -
  3045.                            PROMPT_END);
  3046.  
  3047.         PROMPT_END := PROMPT_END - TEMP_NODE.NAME_LENGTH - 1;
  3048.       end if;
  3049.     end if;
  3050.  
  3051.     TEMP_NODE := TEMP_NODE.PARENT;
  3052.   end loop;
  3053.  
  3054.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(HELP_UTILITY.BLANK_LINE,
  3055.                                       BLANK_LINE_LENGTH);
  3056.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(PROMPT_NAME,
  3057.                       HELP_INFO_SUPPORT.MAX_LINE_LENGTH - PROMPT_END - 1);
  3058.  
  3059. end if;
  3060.  
  3061. exception
  3062.     when others => raise;
  3063. end PRINT_CURRENT_PROMPT;
  3064. ::::::::::
  3065. HELP_RESET.ADA
  3066. ::::::::::
  3067. -------------------------PROLOGUE---------------------------------------
  3068. --                                                                    -*
  3069. -- Unit name    :  RESET_HELP
  3070. -- Date created :  04 March 1985
  3071. -- Last update  :
  3072. --                                                                    -*
  3073. ------------------------------------------------------------------------
  3074. --                                                                    -*
  3075. -- Abstract     :  The procedure sets the help mode flag to true and
  3076. ----------------: resets the current node pointer to the top node of the
  3077. ----------------: tree.
  3078. --                                                                    -*
  3079. ------------------------------------------------------------------------
  3080. --
  3081. -- Mnemonic     :
  3082. -- Name         :
  3083. -- Release date :
  3084. ------------------ Revision history ------------------------------------
  3085. --
  3086. -- DATE  AUTHOR   HISTORY
  3087. --
  3088. --
  3089. --
  3090. --------------------END-PROLOGUE----------------------------------------
  3091.  
  3092.  
  3093. separate (HELP_UTILITY)
  3094. procedure RESET_HELP is
  3095.  
  3096. begin
  3097.  
  3098. HELP_UTILITY.CURRENT_NODE := HELP_UTILITY.TOP_NODE;
  3099.  
  3100. -- set HELP_MODE to on
  3101.  
  3102. HELP_UTILITY.HELP_MODE := true;
  3103. HELP_UTILITY.FIRST_HELP_ME_CALL := true;
  3104.  
  3105. end RESET_HELP;
  3106. ::::::::::
  3107. HELP_TEXT.ADA
  3108. ::::::::::
  3109. -------------------------PROLOGUE---------------------------------------
  3110. --                                                                    -*
  3111. -- Unit name    :  PRINT_TOPIC_TEXT
  3112. -- Date created :  28 January 1985
  3113. -- Last update  :
  3114. --                                                                    -*
  3115. ------------------------------------------------------------------------
  3116. --                                                                    -*
  3117. -- Abstract     : This procedure prints the text assoicated with the
  3118. ----------------: given node.
  3119. --                                                                    -*
  3120. ------------------------------------------------------------------------
  3121. --
  3122. -- Mnemonic     :
  3123. -- Name         :
  3124. -- Release date :
  3125. ------------------ Revision history ------------------------------------
  3126. --
  3127. -- DATE  AUTHOR   HISTORY
  3128. --
  3129. --
  3130. --
  3131. --------------------END-PROLOGUE----------------------------------------
  3132.  
  3133.  
  3134. separate (HELP_UTILITY)
  3135. procedure PRINT_TOPIC_TEXT (NODE: in HELP_UTILITY.HELP_LINK) is
  3136.  
  3137.    CURRENT_LINE: HELP_INFO_SUPPORT.TEXT_LINK;
  3138.  
  3139. begin
  3140.  
  3141. CURRENT_LINE := NODE.TEXT_LINES;
  3142.  
  3143. while CURRENT_LINE /= null loop
  3144.   HELP_INFO_SUPPORT.APPEND_TO_DISPLAY(CURRENT_LINE.TEXT_LINE,
  3145.                                       CURRENT_LINE.LINE_LENGTH);
  3146.   CURRENT_LINE := CURRENT_LINE.NEXT_LINE;
  3147. end loop;
  3148.  
  3149. exception
  3150.     when others => raise;
  3151. end PRINT_TOPIC_TEXT;
  3152. ::::::::::
  3153. help_file_body.ada
  3154. ::::::::::
  3155.  
  3156. with TEXT_IO;
  3157. with HELP_UTILITY;
  3158.  
  3159. package body HELP is
  3160.  
  3161.  procedure HELP_SCREEN (LEVEL: LEVEL_TYPE; HELP_FILE_NAME : string) is
  3162. --------------------------------------------------------------------------
  3163. -- Abstract   : This routine provides a help_screen, based on the two
  3164. --              parameters.
  3165. --------------------------------------------------------------------------
  3166. -- Parameters : LEVEL          - Level of help requested
  3167. --              HELP_FILE_NAME - Name of help file
  3168. --------------------------------------------------------------------------
  3169.  
  3170.  
  3171.  -- Constants and variables
  3172.  
  3173.    HELP_TOPIC : string (1..80);
  3174.    TOPIC_LENGTH : natural;
  3175.    FIRST_CALL: BOOLEAN := TRUE;
  3176.  
  3177.    procedure  OUTPUT_HELP_INFO is
  3178.  
  3179.      HELP_INFO  : string (1..80);
  3180.      HELP_INFO_LENGTH: natural;
  3181.      IS_LAST : BOOLEAN;
  3182.  
  3183.    begin
  3184.  
  3185.      TEXT_IO.NEW_LINE;
  3186.      HELP_UTILITY.GET_TEXT_LINE(HELP_INFO,HELP_INFO_LENGTH,IS_LAST);
  3187.  
  3188.      while not IS_LAST loop
  3189.         TEXT_IO.PUT_LINE(HELP_INFO);
  3190.         TEXT_IO.NEW_LINE;
  3191.         HELP_INFO_LENGTH := HELP_INFO'LENGTH;
  3192.         HELP_UTILITY.GET_TEXT_LINE(HELP_INFO,HELP_INFO_LENGTH,IS_LAST);
  3193.      end loop;
  3194.  
  3195.      TEXT_IO.PUT(HELP_INFO(1..HELP_INFO_LENGTH));
  3196.  
  3197.  
  3198.    end OUTPUT_HELP_INFO;
  3199.  
  3200.  begin       -- begin main procedure
  3201.  
  3202.  --
  3203.  -- Initialize HELP_FILE the first time through
  3204.  --
  3205.  
  3206.      if FIRST_CALL then
  3207.         HELP_UTILITY.INITIALIZE(HELP_FILE_NAME);
  3208.         FIRST_CALL := FALSE;
  3209.      end if;
  3210.  --
  3211.  -- Clear screen
  3212.  --
  3213.  
  3214.     TEXT_IO.NEW_PAGE;
  3215.  
  3216.  --
  3217.  -- Make initial call to HELP entering at level call was made
  3218.  
  3219.        HELP_UTILITY.HELP_ME(LEVEL);
  3220.  
  3221.     --
  3222.     -- Handle other help requests at this level
  3223.     --
  3224.  
  3225.  
  3226.        while not HELP_UTILITY.HELP_IS_TERMINATED loop
  3227.  
  3228.         OUTPUT_HELP_INFO;
  3229.         TEXT_IO.GET_LINE(HELP_TOPIC,TOPIC_LENGTH);
  3230.         HELP_UTILITY.HELP_ME(HELP_TOPIC(1..TOPIC_LENGTH));
  3231.  
  3232.        end loop;
  3233.  
  3234.      TEXT_IO.NEW_LINE;
  3235.      HELP_UTILITY.RESET_HELP;     -- Make sure you reset HELP for future
  3236.                                  -- entries into Help_screen
  3237.  
  3238.  
  3239.    exception
  3240.         when HELP_UTILITY.HELP_FILE_DOES_NOT_EXIST => raise HELP_FILE_ERROR;
  3241.  
  3242.         when HELP_UTILITY.CANNOT_OPEN_HELP_FILE => raise HELP_OPEN_ERROR;
  3243.  
  3244.         when HELP_UTILITY.ILLEGAL_FORMAT_FOR_HELP_FILE =>
  3245.                                                raise HELP_FORMAT_ERROR;
  3246.  
  3247.    end HELP_SCREEN;
  3248.  
  3249.  end HELP;
  3250. ::::::::::
  3251. file_body.ada
  3252. ::::::::::
  3253. with COMMAND_LINE_HANDLER;
  3254. with CURRENT_EXCEPTION;
  3255. with TEXT_IO;
  3256.  
  3257. package body FILE_HANDLING is
  3258.  
  3259.     MAX_FILE_NAME_LENGTH : constant NATURAL := 128;
  3260.     subtype FILE_NAME_STRING is STRING (1 .. MAX_FILE_NAME_LENGTH);
  3261.  
  3262.     FILE_STACK_SIZE        : constant NATURAL := 20;
  3263.     FILE_STACK             : array (1 .. FILE_STACK_SIZE) of TEXT_IO.FILE_TYPE;
  3264.     FILE_STACK_POINTER     : NATURAL := 0;
  3265.     NESTED_FILE_INDICATOR  : constant CHARACTER := '@';
  3266.     EXTENSION_CHAR         : constant CHARACTER := '.';
  3267.     HELP_CHAR              : constant CHARACTER := '?';
  3268.  
  3269.  
  3270.     FILE_NAME              : FILE_NAME_STRING;
  3271.     FILE_NAME_LENGTH       : NATURAL;
  3272.     FLAW_FILE_NAME         : FILE_NAME_STRING;
  3273.     FLAW_FILE_NAME_LENGTH  : NATURAL;
  3274.     FLAW_TYPE              : constant STRING (1 .. 3) := "FLW";
  3275.     STYLE_FILE_NAME        : FILE_NAME_STRING;
  3276.     STYLE_FILE_NAME_LENGTH : NATURAL;
  3277.     STYLE_TYPE             : constant STRING (1 .. 3) := "STY";
  3278.     IS_FILE_NAME_DEFINED   : BOOLEAN := FALSE;
  3279.     COMMAND_LINE_FILE_NAME : constant STRING := "COMMAND_LINE.TXT";
  3280.  
  3281.     NO_MORE_FILES          : exception;
  3282.     INCLUDE_STACK_OVERFLOW : exception;
  3283.     INPUT_FILE_MISSING     : exception;
  3284.     FILE_NAME_ILLEGAL      : exception;
  3285.  
  3286. --
  3287. -- Close the current file on the top of the file stack and pop down
  3288. --  to the next element on the file stack (viz, the file opened before
  3289. --  the file that was just closed).  POP the old file from the top of
  3290. --  the file stack.
  3291. --
  3292.     procedure POP is
  3293.     begin
  3294.         TEXT_IO.CLOSE (FILE_STACK (FILE_STACK_POINTER));
  3295.         FILE_STACK_POINTER := FILE_STACK_POINTER - 1;
  3296.     end POP;
  3297.  
  3298. --
  3299. -- If file stack is not full, increment file stack pointer and open
  3300. --  the file whose name is in FILE_NAME (2..FILE_NAME_LENGTH) as the
  3301. --  new current file on the file stack.  PUSH a new file onto the file
  3302. --  stack.
  3303. --
  3304.     procedure PUSH is
  3305.     begin
  3306.         if FILE_STACK_POINTER = FILE_STACK_SIZE then
  3307.             raise INCLUDE_STACK_OVERFLOW;
  3308.         end if;
  3309.         FILE_STACK_POINTER := FILE_STACK_POINTER + 1;
  3310.         TEXT_IO.OPEN (FILE_STACK (FILE_STACK_POINTER), TEXT_IO.IN_FILE,
  3311.                       FILE_NAME (2 .. FILE_NAME_LENGTH));
  3312.     exception
  3313.         when INCLUDE_STACK_OVERFLOW =>
  3314.             raise;
  3315.         when others =>
  3316.             raise INPUT_FILE_MISSING;
  3317.     end PUSH;
  3318.  
  3319. --
  3320. -- Return the next file name in FILE_NAME and FILE_NAME_LENGTH from
  3321. --  the command line and all included files.
  3322. --
  3323.     procedure RETURN_NEXT_FILE_NAME is
  3324.         INDEX : NATURAL;
  3325.         RETRY : BOOLEAN;
  3326.     begin
  3327. --
  3328. -- Loop until we encounter a file name which is NOT an include file
  3329. --
  3330.         loop
  3331. --
  3332. -- Loop until we encounter a file name
  3333. --
  3334.             loop
  3335.                 RETRY := TRUE;
  3336.                 if FILE_STACK_POINTER = 0 then
  3337.                     begin
  3338.                         COMMAND_LINE_HANDLER.NEXT_WORD
  3339.                            (COMMAND_LINE_FILE_NAME,
  3340.                             FILE_NAME, FILE_NAME_LENGTH);
  3341.                         RETRY := FALSE;
  3342.                     exception
  3343.                         when others =>
  3344.                             raise NO_MORE_FILES;
  3345.                     end;
  3346.                 else
  3347.                     begin
  3348.                         TEXT_IO.GET_LINE
  3349.                            (FILE_STACK (FILE_STACK_POINTER), FILE_NAME,
  3350.                             FILE_NAME_LENGTH);
  3351.                         RETRY := FALSE;
  3352.                     exception
  3353.                         when others =>
  3354.                             POP;
  3355.                             RETRY := TRUE;
  3356.                     end;
  3357.                 end if;
  3358.                 exit when not RETRY;
  3359.             end loop;
  3360.             if FILE_NAME (1) = NESTED_FILE_INDICATOR then
  3361.                 PUSH;
  3362.                 RETRY := TRUE;
  3363.             end if;
  3364.             exit when not RETRY;
  3365.         end loop;
  3366.         --
  3367.         -- If this is the first file name provided, name the Flaw and Style
  3368.         --  files after it
  3369.         --
  3370.         if not IS_FILE_NAME_DEFINED then
  3371.             if FILE_NAME(1) = HELP_CHAR then
  3372.                 raise HELP_ASKED_FOR;
  3373.             else
  3374.                 INDEX := FILE_NAME_LENGTH + 1;
  3375.                 for I in 1 .. FILE_NAME_LENGTH loop
  3376.                     -- search for the LAST EXTENSION character ('.')
  3377.                     -- Note on Data General there can be several '.'
  3378.                     -- in a file name!
  3379.                     if FILE_NAME(I) = EXTENSION_CHAR then
  3380.                         INDEX := I;
  3381.                     end if;
  3382.                 end loop;
  3383.                 FLAW_FILE_NAME (1 .. INDEX+FLAW_TYPE'LAST) :=
  3384.                     FILE_NAME(1..INDEX-1) & EXTENSION_CHAR & FLAW_TYPE;
  3385.                 STYLE_FILE_NAME (1 .. INDEX + STYLE_TYPE'LAST) :=
  3386.                     FILE_NAME(1..INDEX-1) & EXTENSION_CHAR & STYLE_TYPE;
  3387.                 FLAW_FILE_NAME_LENGTH := INDEX + FLAW_TYPE'LAST;
  3388.                 STYLE_FILE_NAME_LENGTH := INDEX + FLAW_TYPE'LAST;
  3389.                 IS_FILE_NAME_DEFINED := TRUE;
  3390.             end if;
  3391.         end if;
  3392.     exception
  3393.         when NO_MORE_FILES =>
  3394.             raise;
  3395.         when HELP_ASKED_FOR =>
  3396.             raise;
  3397.         when others =>
  3398.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3399.             TEXT_IO.PUT_LINE(" in RETURN_NEXT_FILE_NAME.");
  3400.             raise;
  3401.     end RETURN_NEXT_FILE_NAME;
  3402.  
  3403. --
  3404. -- Obtain the next file name and open it
  3405. --
  3406.     procedure INPUT_FILE_ID (FILE_ID    : in out TEXT_IO.FILE_TYPE;
  3407.                              MORE_FILES : out BOOLEAN) is
  3408.         OPEN_SUCCESSFUL : BOOLEAN;
  3409.         CANNOT_OPEN_MSG : constant STRING :=
  3410.             "This file cannot be opened!  : ";
  3411.         STACK_OFLOW_MSG : constant STRING :=
  3412.             "The File-list stack overflowed.  Attempting to continue!?";
  3413.  
  3414.     begin
  3415.       loop
  3416.         begin
  3417.             OPEN_SUCCESSFUL := true;
  3418.             RETURN_NEXT_FILE_NAME;
  3419.             if TEXT_IO.IS_OPEN( FILE_ID ) then
  3420.                 TEXT_IO.CLOSE( FILE_ID );
  3421.             end if;
  3422.             TEXT_IO.OPEN (FILE_ID, TEXT_IO.IN_FILE,
  3423.             FILE_NAME (1 .. FILE_NAME_LENGTH));
  3424.             MORE_FILES := TRUE;
  3425.         exception
  3426.             when TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  3427.                 TEXT_IO.PUT_LINE(CANNOT_OPEN_MSG &
  3428.                                  FILE_NAME(1 .. FILE_NAME_LENGTH) );
  3429.                 OPEN_SUCCESSFUL := false;
  3430.             when INCLUDE_STACK_OVERFLOW =>
  3431.                 TEXT_IO.PUT_LINE(STACK_OFLOW_MSG);
  3432.                 OPEN_SUCCESSFUL := false;
  3433.             when OTHERS =>
  3434.                 raise;
  3435.         end;
  3436.  
  3437.         exit when OPEN_SUCCESSFUL;
  3438.       end loop;
  3439.  
  3440.     exception
  3441.         when TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  3442.             TEXT_IO.PUT_LINE( CANNOT_OPEN_MSG );
  3443.             raise;
  3444.         when HELP_ASKED_FOR =>
  3445.             raise;
  3446.         when NO_MORE_FILES =>
  3447.             MORE_FILES := FALSE;
  3448.         when others =>
  3449.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3450.             TEXT_IO.PUT_LINE(" in RETURN_NEXT_FILE_NAME.");
  3451.             raise FILE_NAME_ILLEGAL;
  3452.     end INPUT_FILE_ID;
  3453.  
  3454. --
  3455. -- Create the Flaw and Style files and return their IDs
  3456. --
  3457.     procedure OUTPUT_FILE_ID (FLAWS_FILE_ID : in out TEXT_IO.FILE_TYPE;
  3458.                               STYLE_FILE_ID : in out TEXT_IO.FILE_TYPE) is
  3459.         CANNOT_OPEN_MSG : constant STRING :=
  3460.           "Cannot OPEN output files!  This program will fail uncleanly!";
  3461.     begin
  3462.         TEXT_IO.CREATE (FLAWS_FILE_ID, TEXT_IO.OUT_FILE,
  3463.                         FLAW_FILE_NAME (1 .. FLAW_FILE_NAME_LENGTH));
  3464.         TEXT_IO.CREATE (STYLE_FILE_ID, TEXT_IO.OUT_FILE,
  3465.                         STYLE_FILE_NAME (1 .. STYLE_FILE_NAME_LENGTH));
  3466.  
  3467.     exception
  3468.         when TEXT_IO.NAME_ERROR | TEXT_IO.USE_ERROR =>
  3469.             TEXT_IO.PUT_LINE( CANNOT_OPEN_MSG );
  3470.             raise;
  3471.         when OTHERS =>
  3472.             raise;
  3473.     end OUTPUT_FILE_ID;
  3474.  
  3475.  
  3476. end FILE_HANDLING;
  3477. ::::::::::
  3478. tokenz_body.ada
  3479. ::::::::::
  3480. with FILE_HANDLING;
  3481. with CURRENT_EXCEPTION;
  3482. with DYN;
  3483. use DYN;                                         -- must use use to overload
  3484.                                                  -- operators
  3485. package body TOKENIZER is
  3486. --------------------------------------------------------------------------
  3487. -- Abstract   : This is the body to the Tokenizer package.  This body
  3488. --              contains all the routines to build the token chain from
  3489. --              the input Ada source.
  3490. --------------------------------------------------------------------------
  3491.  
  3492. -- types used for input files
  3493.  
  3494.     subtype LINE_STRING is STRING(1..LINE_INDEX_RANGE'LAST);
  3495.                                                  -- an input line record
  3496.     subtype LINE_COLUMN is INTEGER range -1..LINE_INDEX_RANGE'LAST;
  3497.  
  3498.     type LINE_RECORD is                          -- Buffer containing current
  3499.         record                                   -- Line of file
  3500.             LINE : LINE_STRING;                  -- Line of text
  3501.             COLUMN : LINE_COLUMN := 0;           -- Current column
  3502.             LENGTH : LINE_COLUMN := 0;           -- Length of current line
  3503.         end record;
  3504.  
  3505. -- "global" variables
  3506.  
  3507.     CURRENT_LINE_NUMBER : LINE_NUM_RANGE := 0;
  3508.     CURRENT_LINE : LINE_RECORD;
  3509.     ID : DYN.DYN_STRING;                              -- Current identifier
  3510.     ROOT : IDENTIFIER_TREE := null;              -- Root of binary tree
  3511.     ROOT_TOKEN : TOKEN_POINTER;                  -- First token
  3512.     INPUT_FILE : TEXT_IO.FILE_TYPE;
  3513.  
  3514.     END_LINE : exception;
  3515.     END_FILE : exception;
  3516.  
  3517. -- Internal procedures and functions
  3518.  
  3519.     procedure INSERT                             -- Insert identifier into tree
  3520.                            (STRG : in DYN.DYN_STRING; -- String to be inserted
  3521.                             T : in out IDENTIFIER_TREE);
  3522.                                                  -- Tree to add it to
  3523.     function IS_A_RESERVED_WORD                  -- determines if Id is a
  3524.                                                  -- reserved word
  3525.                            (ID : in DYN.DYN_STRING)   -- String to check
  3526.                             return BOOLEAN;
  3527.     function RESERVED_WORD (ID : in DYN.DYN_STRING)
  3528.                             return KEYWORDS;
  3529.     function NEXT_CHARACTER return CHARACTER;    -- Gets next character from
  3530.                                                  -- input file
  3531.     function NEXT_IDENTIFIER return TOKEN;       -- Gets next token from input
  3532.  
  3533.  
  3534.     procedure INSERT(STRG : in DYN.DYN_STRING;
  3535.                      T : in out IDENTIFIER_TREE) is separate;
  3536.  
  3537.     function IS_A_RESERVED_WORD(ID : in DYN.DYN_STRING)
  3538.                 return BOOLEAN is separate;
  3539.     function RESERVED_WORD (ID : in DYN.DYN_STRING) return KEYWORDS is separate;
  3540.     function NEXT_CHARACTER return CHARACTER is separate;
  3541.     function NEXT_IDENTIFIER return TOKEN is separate;
  3542.     function TREE_ROOT return IDENTIFIER_TREE is separate;
  3543.  
  3544.  
  3545.     function EXTERNAL_REPRESENTATION(CURRENT_TOKEN : in TOKEN) return
  3546.              DYN.DYN_STRING is
  3547. --------------------------------------------------------------------------
  3548. -- Abstract   : This function returns the exact physical represeantation
  3549. --              in the input source for the token.
  3550. --------------------------------------------------------------------------
  3551. -- Parameters : CURRENT_TOKEN - Token to give representation for
  3552. --------------------------------------------------------------------------
  3553.  
  3554.         ANSWER : DYN.DYN_STRING;
  3555.  
  3556.         begin
  3557.             case CURRENT_TOKEN.TYPE_OF_TOKEN is
  3558.                 --  Check for tokens that have a constant representation
  3559.                 --  ( operators , etc.)
  3560.                 when END_OF_LINE =>
  3561.                     ANSWER := D_STRING("");
  3562.                 when CONCATENATION_OPERATOR =>
  3563.                     ANSWER := D_STRING("&");
  3564.                 when TICK =>
  3565.                     ANSWER := D_STRING("'");
  3566.                 when RIGHT_PARENTHESIS =>
  3567.                     ANSWER := D_STRING(")");
  3568.                 when LEFT_PARENTHESIS =>
  3569.                     ANSWER := D_STRING("(");
  3570.                 when MULTIPLICATION_OPERATOR =>
  3571.                     ANSWER := D_STRING("*");
  3572.                 when ADDITION_OPERATOR =>
  3573.                     ANSWER := D_STRING("+");
  3574.                 when COMMA =>
  3575.                     ANSWER := D_STRING(",");
  3576.                 when SUBTRACTION_OPERATOR =>
  3577.                     ANSWER := D_STRING("-");
  3578.                 when PERIOD =>
  3579.                     ANSWER := D_STRING(".");
  3580.                 when DIVISION_OPERATOR =>
  3581.                     ANSWER := D_STRING("/");
  3582.                 when COLON =>
  3583.                     ANSWER := D_STRING(":");
  3584.                 when SEMICOLON =>
  3585.                     ANSWER := D_STRING(";");
  3586.                 when LESS_THAN_OPERATOR =>
  3587.                     ANSWER := D_STRING("<");
  3588.                 when EQUAL_OPERATOR =>
  3589.                     ANSWER := D_STRING("=");
  3590.                 when GREATER_THAN_OPERATOR =>
  3591.                     ANSWER := D_STRING(">");
  3592.                 when VERTICAL_BAR =>
  3593.                     ANSWER := D_STRING("|");
  3594.                 when COMMENT =>
  3595.                     ANSWER := D_STRING("--") &
  3596.                         CURRENT_TOKEN.PHYSICAL_REPRESENTATION;
  3597.                 when ARROW =>
  3598.                     ANSWER := D_STRING("=>");
  3599.                 when DOUBLE_DOT =>
  3600.                     ANSWER := D_STRING("..");
  3601.                 when EXPONENTIATE_OPERATOR =>
  3602.                     ANSWER := D_STRING("**");
  3603.                 when ASSIGNMENT_OPERATOR =>
  3604.                     ANSWER := D_STRING(":=");
  3605.                 when INEQUAL_OPERATOR =>
  3606.                     ANSWER := D_STRING("/=");
  3607.                 when GREATER_THAN_OR_EQUAL_OPERATOR =>
  3608.                     ANSWER := D_STRING(">=");
  3609.                 when LESS_THAN_OR_EQUAL_OPERATOR =>
  3610.                     ANSWER := D_STRING("<=");
  3611.                 when LEFT_LABEL_BRACKET =>
  3612.                     ANSWER := D_STRING("<<");
  3613.                 when RIGHT_LABEL_BRACKET =>
  3614.                     ANSWER := D_STRING(">>");
  3615.                 when BOX =>
  3616.                     ANSWER := D_STRING("<>");
  3617.                 when STRING_LITERAL =>
  3618.                     ANSWER := D_STRING('"') &
  3619.                         CURRENT_TOKEN.PHYSICAL_REPRESENTATION & D_STRING('"');
  3620.                 when CHARACTER_LITERAL =>
  3621.                     ANSWER := D_STRING("'") &
  3622.                         CURRENT_TOKEN.PHYSICAL_REPRESENTATION & D_STRING("'");
  3623.                 when others =>
  3624.                     ANSWER := CURRENT_TOKEN.PHYSICAL_REPRESENTATION;
  3625.             end case;
  3626.             return ANSWER;
  3627.             exception
  3628.                 when others =>
  3629.                     TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3630.                     TEXT_IO.PUT_LINE(" in EXTERNAL_REPRESENTATION");
  3631.                     raise;
  3632.         end  EXTERNAL_REPRESENTATION;
  3633.  
  3634.     function FIRST_TOKEN return TOKEN is
  3635. --------------------------------------------------------------------------
  3636. -- Abstract   : This function returns the first token in the input file.
  3637. --              The first token is used as a starting point by the
  3638. --              Style_Checker.
  3639. --------------------------------------------------------------------------
  3640.         begin
  3641.             return ROOT_TOKEN.all;
  3642.             exception
  3643.                 when others =>
  3644.                     TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3645.                     TEXT_IO.PUT_LINE(" in FIRST_TOKEN");
  3646.                     raise;
  3647.         end FIRST_TOKEN;
  3648.  
  3649.     function LENGTH_OF_COMMENT(CURRENT_TOKEN : in TOKEN) return NATURAL is
  3650. --------------------------------------------------------------------------
  3651. -- Abstract   : This routine returns the length of a comment token
  3652. --------------------------------------------------------------------------
  3653. -- Parameters : CURRENT_TOKEN - Comment token
  3654. --------------------------------------------------------------------------
  3655.         begin
  3656.             if TYPE_OF_TOKEN_IS(CURRENT_TOKEN) = COMMENT then
  3657.                 return LENGTH(CURRENT_TOKEN.PHYSICAL_REPRESENTATION);
  3658.             else
  3659.                 raise INVALID_TOKEN;
  3660.             end if;
  3661.             exception
  3662.                 when INVALID_TOKEN => raise;
  3663.                 when others =>
  3664.                     TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3665.                     TEXT_IO.PUT_LINE(" in LENGTH_OF_COMMENT");
  3666.                     raise;
  3667.         end LENGTH_OF_COMMENT;
  3668.  
  3669.     function NEXT_TOKEN(CURRENT_TOKEN : in TOKEN) return TOKEN is
  3670. --------------------------------------------------------------------------
  3671. -- Abstract   : This function returns the token in the input stream that
  3672. --              follows the token input to this routine.
  3673. --------------------------------------------------------------------------
  3674. -- Parameters : CURRENT_TOKEN - Return token that follows this token
  3675. --------------------------------------------------------------------------
  3676.         begin
  3677.             if CURRENT_TOKEN.NEXT_TOKEN /= null then
  3678.                 return CURRENT_TOKEN.NEXT_TOKEN.all;
  3679.             else
  3680.                 raise END_OF_TOKENS;
  3681.             end if;
  3682.             exception
  3683.                 when END_OF_TOKENS => raise;
  3684.                 when others =>
  3685.                     TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3686.                     TEXT_IO.PUT_LINE(" in NEXT_TOKEN");
  3687.                     raise;
  3688.         end  NEXT_TOKEN;
  3689.  
  3690.     function PREVIOUS_TOKEN(CURRENT_TOKEN : in TOKEN) return TOKEN is
  3691. --------------------------------------------------------------------------
  3692. -- Abstract   : This function returns the token in the input stream that
  3693. --              precedes the token input to this routine.
  3694. --------------------------------------------------------------------------
  3695. -- Parameters : CURRENT_TOKEN - Return token that precedes this token
  3696. --------------------------------------------------------------------------
  3697.         begin
  3698.             if CURRENT_TOKEN.PREVIOUS_TOKEN /= null then
  3699.                 return CURRENT_TOKEN.PREVIOUS_TOKEN.all;
  3700.             else
  3701.                 raise END_OF_TOKENS;
  3702.             end if;
  3703.             exception
  3704.                 when END_OF_TOKENS => raise;
  3705.                 when others =>
  3706.                     TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3707.                     TEXT_IO.PUT_LINE(" in PREVIOUS_TOKEN");
  3708.                     raise;
  3709.         end  PREVIOUS_TOKEN;
  3710.  
  3711.     function TYPE_OF_TOKEN_IS(CURRENT_TOKEN : in TOKEN) return TOKEN_TYPE is
  3712. --------------------------------------------------------------------------
  3713. -- Abstract   : This function returns the type associated with the input
  3714. --              token.
  3715. --------------------------------------------------------------------------
  3716. -- Parameters : CURRENT_TOKEN - Token to return type of.
  3717. --------------------------------------------------------------------------
  3718.         begin
  3719.             return CURRENT_TOKEN.TYPE_OF_TOKEN;
  3720.             exception
  3721.                 when others =>
  3722.                     TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3723.                     TEXT_IO.PUT_LINE(" in TYPE_OF_TOKEN_IS");
  3724.                     raise;
  3725.         end  TYPE_OF_TOKEN_IS;
  3726.  
  3727.     procedure BUILD_TOKENS is separate;
  3728.  
  3729.     procedure TOKEN_POSITION(CURRENT_TOKEN : in TOKEN;
  3730.                              LINE : out LINE_NUM_RANGE;
  3731.                              COLUMN : out LINE_INDEX_RANGE) is
  3732. --------------------------------------------------------------------------
  3733. -- Abstract   : This routine returns the line and column position of the
  3734. --              input token.
  3735. --------------------------------------------------------------------------
  3736. -- Parameters : CURRENT_TOKEN - Input token
  3737. --              LINE          - Line number associated with input token
  3738. --              COLUMN        - Column number associated with input token
  3739. --------------------------------------------------------------------------
  3740.         begin
  3741.             LINE := CURRENT_TOKEN.TOKEN_POSITION.LINE;
  3742.             COLUMN := CURRENT_TOKEN.TOKEN_POSITION.COLUMN;
  3743.             exception
  3744.                 when others =>
  3745.                     TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3746.                     TEXT_IO.PUT_LINE(" in TOKEN_POSITION");
  3747.                     raise;
  3748.         end TOKEN_Position;
  3749.  
  3750.     procedure LINE_CONTAINING_TOKEN(CURRENT_TOKEN : in TOKEN;
  3751.                                     LINE : out DYN.DYN_STRING) is separate;
  3752.  
  3753. end TOKENIZER;
  3754. ::::::::::
  3755. insert.ada
  3756. ::::::::::
  3757. separate (TOKENIZER)
  3758.  
  3759. procedure INSERT                                -- Insert identifier into tree
  3760.         (STRG : in DYN.DYN_STRING;              -- String to be inserted
  3761.          T : in out IDENTIFIER_TREE) is         -- Tree to add it to
  3762. --------------------------------------------------------------------------
  3763. -- Abstract   : This routine inserts an identifier into the binary tree
  3764. --              of identifiers exported by the Tokenizer package.
  3765. --------------------------------------------------------------------------
  3766. -- Parameters : STRG    - Identifier to add to tree (if not already in it)
  3767. --              T       - Root of tree to add it to.
  3768. --------------------------------------------------------------------------
  3769. -- Algorithm  : Typical binary tree insertion.
  3770. --                  If T is null then insert identifier at T
  3771. --                  Else
  3772. --                      If T is the identifier add new reference
  3773. --                      Else
  3774. --                          Recursively call this routine with
  3775. --                              Left or Right pointer
  3776. --------------------------------------------------------------------------
  3777.  
  3778.     FOLLOW_CHAIN : REFPTR;
  3779.  
  3780. begin
  3781.     if T = null then                            -- add to tree here
  3782.         T := new IDENTIFIER_NODE;
  3783.         T.LEFT := null;
  3784.         T.RIGHT := null;
  3785.         T.REFERENCES := new REFS;
  3786.         T.REFERENCES.STRG := STRG;
  3787.         T.REFERENCES.NEXT := null;
  3788.     else
  3789.         if UPPER_CASE(T.REFERENCES.STRG) =      -- new reference to identifier
  3790.             UPPER_CASE(STRG) then
  3791.             FOLLOW_CHAIN := T.REFERENCES;
  3792.             while FOLLOW_CHAIN.NEXT /= null loop
  3793.                 FOLLOW_CHAIN := FOLLOW_CHAIN.NEXT;
  3794.             end loop;
  3795.             FOLLOW_CHAIN.NEXT := new REFS;
  3796.             FOLLOW_CHAIN.NEXT.NEXT := null;
  3797.             FOLLOW_CHAIN.NEXT.STRG := STRG;
  3798.         else
  3799.             if UPPER_CASE(T.REFERENCES.STRG) > UPPER_CASE(STRG) then
  3800.                 INSERT(STRG,T.LEFT);
  3801.             else
  3802.                 INSERT(STRG,T.RIGHT);
  3803.             end if;
  3804.         end if;
  3805.     end if;
  3806.     exception
  3807.         when others =>
  3808.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3809.             TEXT_IO.PUT_LINE("in INSERT");
  3810.             raise;
  3811. end INSERT;
  3812. ::::::::::
  3813. is_a_reserved_word.ada
  3814. ::::::::::
  3815. separate (TOKENIZER)
  3816.  
  3817. function IS_A_RESERVED_WORD                     -- determines if Id is a
  3818.                                                 -- reserved word
  3819.         (ID : in DYN.DYN_STRING) return BOOLEAN is   -- String to check
  3820. --------------------------------------------------------------------------
  3821. -- Abstract   : This function returns true if the input name is an Ada
  3822. --              reserved word, otherwise it returns false.
  3823. --------------------------------------------------------------------------
  3824. -- Parameters : ID      - Name to check
  3825. --------------------------------------------------------------------------
  3826.  
  3827.     ANSWER : BOOLEAN;                           -- this is the return
  3828. begin
  3829.     case DYN.LENGTH(ID) is
  3830.         when 2 => ANSWER := UPPER_CASE(ID) = "AT"
  3831.                          or UPPER_CASE(ID) = "DO"
  3832.                          or UPPER_CASE(ID) = "IF"
  3833.                          or UPPER_CASE(ID) = "IN"
  3834.                          or UPPER_CASE(ID) = "IS"
  3835.                          or UPPER_CASE(ID) = "OF"
  3836.                          or UPPER_CASE(ID) = "OR";
  3837.         when 3 => ANSWER := UPPER_CASE(ID) = "ABS"
  3838.                          or UPPER_CASE(ID) = "ALL"
  3839.                          or UPPER_CASE(ID) = "AND"
  3840.                          or UPPER_CASE(ID) = "END"
  3841.                          or UPPER_CASE(ID) = "FOR"
  3842.                          or UPPER_CASE(ID) = "MOD"
  3843.                          or UPPER_CASE(ID) = "NEW"
  3844.                          or UPPER_CASE(ID) = "NOT"
  3845.                          or UPPER_CASE(ID) = "OUT"
  3846.                          or UPPER_CASE(ID) = "REM"
  3847.                          or UPPER_CASE(ID) = "USE"
  3848.                          or UPPER_CASE(ID) = "XOR";
  3849.         when 4 => ANSWER := UPPER_CASE(ID) = "BODY"
  3850.                          or UPPER_CASE(ID) = "CASE"
  3851.                          or UPPER_CASE(ID) = "ELSE"
  3852.                          or UPPER_CASE(ID) = "EXIT"
  3853.                          or UPPER_CASE(ID) = "GOTO"
  3854.                          or UPPER_CASE(ID) = "LOOP"
  3855.                          or UPPER_CASE(ID) = "NULL"
  3856.                          or UPPER_CASE(ID) = "TASK"
  3857.                          or UPPER_CASE(ID) = "THEN"
  3858.                          or UPPER_CASE(ID) = "TYPE"
  3859.                          or UPPER_CASE(ID) = "WHEN"
  3860.                          or UPPER_CASE(ID) = "WITH";
  3861.         when 5 => ANSWER := UPPER_CASE(ID) = "ABORT"
  3862.                          or UPPER_CASE(ID) = "ARRAY"
  3863.                          or UPPER_CASE(ID) = "BEGIN"
  3864.                          or UPPER_CASE(ID) = "DELAY"
  3865.                          or UPPER_CASE(ID) = "DELTA"
  3866.                          or UPPER_CASE(ID) = "ELSIF"
  3867.                          or UPPER_CASE(ID) = "ENTRY"
  3868.                          or UPPER_CASE(ID) = "RAISE"
  3869.                          or UPPER_CASE(ID) = "RANGE"
  3870.                          or UPPER_CASE(ID) = "WHILE";
  3871.         when 6 => ANSWER := UPPER_CASE(ID) = "ACCEPT"
  3872.                          or UPPER_CASE(ID) = "ACCESS"
  3873.                          or UPPER_CASE(ID) = "DIGITS"
  3874.                          or UPPER_CASE(ID) = "OTHERS"
  3875.                          or UPPER_CASE(ID) = "PRAGMA"
  3876.                          or UPPER_CASE(ID) = "RECORD"
  3877.                          or UPPER_CASE(ID) = "RETURN"
  3878.                          or UPPER_CASE(ID) = "SELECT";
  3879.         when 7 => ANSWER := UPPER_CASE(ID) = "DECLARE"
  3880.                          or UPPER_CASE(ID) = "GENERIC"
  3881.                          or UPPER_CASE(ID) = "LIMITED"
  3882.                          or UPPER_CASE(ID) = "PACKAGE"
  3883.                          or UPPER_CASE(ID) = "PRIVATE"
  3884.                          or UPPER_CASE(ID) = "RENAMES"
  3885.                          or UPPER_CASE(ID) = "REVERSE"
  3886.                          or UPPER_CASE(ID) = "SUBTYPE";
  3887.         when 8 => ANSWER := UPPER_CASE(ID) = "CONSTANT"
  3888.                          or UPPER_CASE(ID) = "FUNCTION"
  3889.                          or UPPER_CASE(ID) = "SEPARATE";
  3890.         when 9 => ANSWER := UPPER_CASE(ID) = "EXCEPTION"
  3891.                          or UPPER_CASE(ID) = "PROCEDURE"
  3892.                          or UPPER_CASE(ID) = "TERMINATE";
  3893.         when OTHERS => ANSWER := FALSE;
  3894.     end case;
  3895.     return ANSWER;
  3896.     exception
  3897.         when others =>
  3898.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  3899.             TEXT_IO.PUT_LINE("in IS_A_RESERVED_WORD");
  3900.             raise;
  3901. end IS_A_RESERVED_WORD;
  3902. ::::::::::
  3903. reserved_word.ada
  3904. ::::::::::
  3905.  
  3906. separate (TOKENIZER)
  3907.  
  3908. function RESERVED_WORD (ID : in DYN.DYN_STRING) return KEYWORDS is
  3909. --------------------------------------------------------------------------
  3910. -- Abstract   : This function returns the Keywords enumeration value of
  3911. --              the input reserve word string.
  3912. --------------------------------------------------------------------------
  3913. -- Parameters : ID      - The string representation of  some reserve word
  3914. --------------------------------------------------------------------------
  3915.  
  3916.     ANSWER : KEYWORDS;                          -- this is the return
  3917. begin
  3918.     case DYN.LENGTH(ID) is
  3919.         when 2 =>
  3920.             if UPPER_CASE(ID) = "AT" then
  3921.                 ANSWER := AT_TOKEN;
  3922.             elsif UPPER_CASE(ID) = "DO" then
  3923.                 ANSWER := DO_TOKEN;
  3924.             elsif UPPER_CASE(ID) = "IF" then
  3925.                 ANSWER := IF_TOKEN;
  3926.             elsif UPPER_CASE(ID) = "IN" then
  3927.                 ANSWER := IN_TOKEN;
  3928.             elsif UPPER_CASE(ID) = "IS" then
  3929.                 ANSWER := IS_TOKEN;
  3930.             elsif UPPER_CASE(ID) = "OF" then
  3931.                 ANSWER := OF_TOKEN;
  3932.             elsif UPPER_CASE(ID) = "OR" then
  3933.                 ANSWER := OR_TOKEN;
  3934.             else raise INVALID_TOKEN;
  3935.             end if;
  3936.         when 3 =>
  3937.             if UPPER_CASE(ID) = "ABS" then
  3938.                 ANSWER := ABS_TOKEN;
  3939.             elsif UPPER_CASE(ID) = "ALL" then
  3940.                 ANSWER := ALL_TOKEN;
  3941.             elsif UPPER_CASE(ID) = "AND" then
  3942.                 ANSWER := AND_TOKEN;
  3943.             elsif UPPER_CASE(ID) = "END" then
  3944.                 ANSWER := END_TOKEN;
  3945.             elsif UPPER_CASE(ID) = "FOR" then
  3946.                 ANSWER := FOR_TOKEN;
  3947.             elsif UPPER_CASE(ID) = "MOD" then
  3948.                 ANSWER := MOD_TOKEN;
  3949.             elsif UPPER_CASE(ID) = "NEW" then
  3950.                 ANSWER := NEW_TOKEN;
  3951.             elsif UPPER_CASE(ID) = "NOT" then
  3952.                 ANSWER := NOT_TOKEN;
  3953.             elsif UPPER_CASE(ID) = "OUT" then
  3954.                 ANSWER := OUT_TOKEN;
  3955.             elsif UPPER_CASE(ID) = "REM" then
  3956.                 ANSWER := REM_TOKEN;
  3957.             elsif UPPER_CASE(ID) = "USE" then
  3958.                 ANSWER := USE_TOKEN;
  3959.             elsif UPPER_CASE(ID) = "XOR" then
  3960.                 ANSWER := XOR_TOKEN;
  3961.             else raise INVALID_TOKEN;
  3962.             end if;
  3963.         when 4 =>
  3964.             if UPPER_CASE(ID) = "BODY" then
  3965.                 ANSWER := BODY_TOKEN;
  3966.             elsif UPPER_CASE(ID) = "CASE" then
  3967.                 ANSWER := CASE_TOKEN;
  3968.             elsif UPPER_CASE(ID) = "ELSE" then
  3969.                 ANSWER := ELSE_TOKEN;
  3970.             elsif UPPER_CASE(ID) = "EXIT" then
  3971.                 ANSWER := EXIT_TOKEN;
  3972.             elsif UPPER_CASE(ID) = "GOTO" then
  3973.                 ANSWER := GOTO_TOKEN;
  3974.             elsif UPPER_CASE(ID) = "LOOP" then
  3975.                 ANSWER := LOOP_TOKEN;
  3976.             elsif UPPER_CASE(ID) = "NULL" then
  3977.                 ANSWER := NULL_TOKEN;
  3978.             elsif UPPER_CASE(ID) = "TASK" then
  3979.                 ANSWER := TASK_TOKEN;
  3980.             elsif UPPER_CASE(ID) = "THEN" then
  3981.                 ANSWER := THEN_TOKEN;
  3982.             elsif UPPER_CASE(ID) = "TYPE" then
  3983.                 ANSWER := TYPE_TOKEN;
  3984.             elsif UPPER_CASE(ID) = "WHEN" then
  3985.                 ANSWER := WHEN_TOKEN;
  3986.             elsif UPPER_CASE(ID) = "WITH" then
  3987.                 ANSWER := WITH_TOKEN;
  3988.             else raise INVALID_TOKEN;
  3989.             end if;
  3990.         when 5 =>
  3991.             if UPPER_CASE(ID) = "ABORT" then
  3992.                 ANSWER := ABORT_TOKEN;
  3993.             elsif UPPER_CASE(ID) = "ARRAY" then
  3994.                 ANSWER := ARRAY_TOKEN;
  3995.             elsif UPPER_CASE(ID) = "BEGIN" then
  3996.                 ANSWER := BEGIN_TOKEN;
  3997.             elsif UPPER_CASE(ID) = "DELAY" then
  3998.                 ANSWER := DELAY_TOKEN;
  3999.             elsif UPPER_CASE(ID) = "DELTA" then
  4000.                 ANSWER := DELTA_TOKEN;
  4001.             elsif UPPER_CASE(ID) = "ELSIF" then
  4002.                 ANSWER := ELSIF_TOKEN;
  4003.             elsif UPPER_CASE(ID) = "ENTRY" then
  4004.                 ANSWER := ENTRY_TOKEN;
  4005.             elsif UPPER_CASE(ID) = "RAISE" then
  4006.                 ANSWER := RAISE_TOKEN;
  4007.             elsif UPPER_CASE(ID) = "RANGE" then
  4008.                 ANSWER := RANGE_TOKEN;
  4009.             elsif UPPER_CASE(ID) = "WHILE" then
  4010.                 ANSWER := WHILE_TOKEN;
  4011.             else raise INVALID_TOKEN;
  4012.             end if;
  4013.         when 6 =>
  4014.             if UPPER_CASE(ID) = "ACCEPT" then
  4015.                 ANSWER := ACCEPT_TOKEN;
  4016.             elsif UPPER_CASE(ID) = "ACCESS" then
  4017.                 ANSWER := ACCESS_TOKEN;
  4018.             elsif UPPER_CASE(ID) = "DIGITS" then
  4019.                 ANSWER := DIGITS_TOKEN;
  4020.             elsif UPPER_CASE(ID) = "OTHERS" then
  4021.                 ANSWER := OTHERS_TOKEN;
  4022.             elsif UPPER_CASE(ID) = "PRAGMA" then
  4023.                 ANSWER := PRAGMA_TOKEN;
  4024.             elsif UPPER_CASE(ID) = "RECORD" then
  4025.                 ANSWER := RECORD_TOKEN;
  4026.             elsif UPPER_CASE(ID) = "RETURN" then
  4027.                 ANSWER := RETURN_TOKEN;
  4028.             elsif UPPER_CASE(ID) = "SELECT" then
  4029.                 ANSWER := SELECT_TOKEN;
  4030.             else raise INVALID_TOKEN;
  4031.             end if;
  4032.         when 7 =>
  4033.             if UPPER_CASE(ID) = "DECLARE" then
  4034.                 ANSWER := DECLARE_TOKEN;
  4035.             elsif UPPER_CASE(ID) = "GENERIC" then
  4036.                 ANSWER := GENERIC_TOKEN;
  4037.             elsif UPPER_CASE(ID) = "LIMITED" then
  4038.                 ANSWER := LIMITED_TOKEN;
  4039.             elsif UPPER_CASE(ID) = "PACKAGE" then
  4040.                 ANSWER := PACKAGE_TOKEN;
  4041.             elsif UPPER_CASE(ID) = "PRIVATE" then
  4042.                 ANSWER := PRIVATE_TOKEN;
  4043.             elsif UPPER_CASE(ID) = "RENAMES" then
  4044.                 ANSWER := RENAMES_TOKEN;
  4045.             elsif UPPER_CASE(ID) = "REVERSE" then
  4046.                 ANSWER := REVERSE_TOKEN;
  4047.             elsif UPPER_CASE(ID) = "SUBTYPE" then
  4048.                 ANSWER := SUBTYPE_TOKEN;
  4049.             else raise INVALID_TOKEN;
  4050.             end if;
  4051.         when 8 =>
  4052.             if UPPER_CASE(ID) = "CONSTANT" then
  4053.                 ANSWER := CONSTANT_TOKEN;
  4054.             elsif UPPER_CASE(ID) = "FUNCTION" then
  4055.                 ANSWER := FUNCTION_TOKEN;
  4056.             elsif UPPER_CASE(ID) = "SEPARATE" then
  4057.                 ANSWER := SEPARATE_TOKEN;
  4058.             else raise INVALID_TOKEN;
  4059.             end if;
  4060.         when 9 =>
  4061.             if UPPER_CASE(ID) = "EXCEPTION" then
  4062.                 ANSWER := EXCEPTION_TOKEN;
  4063.             elsif UPPER_CASE(ID) = "PROCEDURE" then
  4064.                 ANSWER := PROCEDURE_TOKEN;
  4065.             elsif UPPER_CASE(ID) = "TERMINATE" then
  4066.                 ANSWER := TERMINATE_TOKEN;
  4067.             else raise INVALID_TOKEN;
  4068.             end if;
  4069.         when OTHERS => raise INVALID_TOKEN;
  4070.     end case;
  4071.     return ANSWER;
  4072.     exception
  4073.         when others =>
  4074.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4075.             TEXT_IO.PUT_LINE(" in RESERVED_WORD");
  4076.             raise;
  4077. end RESERVED_WORD;
  4078. ::::::::::
  4079. next_character.ada
  4080. ::::::::::
  4081. separate (TOKENIZER)
  4082.  
  4083. function NEXT_CHARACTER return CHARACTER is     -- Gets next character from
  4084.                                                 -- input file
  4085. --------------------------------------------------------------------------
  4086. -- Abstract   : This function returns the next character to be parsed
  4087. --              by the tokenizer build_tokens procedure.  This routine
  4088. --              also translates horizontal tabs into the correct number
  4089. --              of spaces (based on the constant TAB_LENGTH).
  4090. --------------------------------------------------------------------------
  4091.  
  4092.     TAB_LENGTH  : constant NATURAL := 8;
  4093.  
  4094.     SPACES_TO_ADD : NATURAL;                    -- Used if tab is found
  4095.  
  4096.     procedure GET_LINE(LINE : out LINE_RECORD) is
  4097.         NEW_INPUT_LINE : LINE_STRING;           -- parameters sent to TEXT_IO
  4098.         NEW_INPUT_LINE_LENGTH : LINE_COLUMN;
  4099.     begin
  4100.         if TEXT_IO.END_OF_FILE(INPUT_FILE) then
  4101.             CURRENT_LINE_NUMBER := CURRENT_LINE_NUMBER + 1;
  4102.             LINE.LENGTH := -1;
  4103.             LINE.COLUMN := 0;
  4104.         else
  4105.             CURRENT_LINE_NUMBER := CURRENT_LINE_NUMBER + 1;
  4106.             TEXT_IO.GET_LINE(INPUT_FILE,NEW_INPUT_LINE,NEW_INPUT_LINE_LENGTH);
  4107.             LINE.LINE(1..NEW_INPUT_LINE_LENGTH + 1) :=
  4108.                 NEW_INPUT_LINE(1..NEW_INPUT_LINE_LENGTH) & " ";
  4109.             LINE.COLUMN := 0;
  4110.             LINE.LENGTH := NEW_INPUT_LINE_LENGTH + 1;
  4111.         end if;
  4112.     exception
  4113.         when others =>
  4114.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4115.             TEXT_IO.PUT_LINE("in GET_LINE");
  4116.             raise;
  4117.     end GET_LINE;
  4118.  
  4119. begin
  4120.     if CURRENT_LINE.COLUMN < CURRENT_LINE.LENGTH  then
  4121.         CURRENT_LINE.COLUMN := CURRENT_LINE.COLUMN + 1;
  4122.         if CURRENT_LINE.LINE(CURRENT_LINE.COLUMN) /= ASCII.HT then
  4123.             return CURRENT_LINE.LINE(CURRENT_LINE.COLUMN);
  4124.         else   -- special case to handle tabs in input!
  4125.             CURRENT_LINE.LINE(CURRENT_LINE.COLUMN) := ' ';
  4126.             SPACES_TO_ADD := TAB_LENGTH - (CURRENT_LINE.COLUMN mod TAB_LENGTH);
  4127.             CURRENT_LINE.LINE(CURRENT_LINE.COLUMN + SPACES_TO_ADD..
  4128.                               CURRENT_LINE.LENGTH + SPACES_TO_ADD) :=
  4129.                 CURRENT_LINE.LINE(CURRENT_LINE.COLUMN..CURRENT_LINE.LENGTH);
  4130.             for I in 1..SPACES_TO_ADD loop
  4131.                 CURRENT_LINE.LINE(CURRENT_LINE.COLUMN + I - 1) := ' ';
  4132.             end loop;
  4133.             CURRENT_LINE.LENGTH := CURRENT_LINE.LENGTH + SPACES_TO_ADD;
  4134.             return ' ';
  4135.         end if;
  4136.     elsif CURRENT_LINE.LENGTH > -1 then
  4137.         GET_LINE(CURRENT_LINE);
  4138.         if CURRENT_LINE_NUMBER /= 1 then
  4139.             raise END_LINE;
  4140.         else    -- if CURRENT_LINE_NUMBER is 1 then this is the first time
  4141.                 -- through NEXT_CHARACTER, so get next character
  4142.             return NEXT_CHARACTER;
  4143.         end if;
  4144.     else
  4145.         raise END_FILE;
  4146.     end if;
  4147.     exception
  4148.         when END_LINE | END_FILE => raise;              -- Let 'em go
  4149.         when others =>
  4150.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4151.             TEXT_IO.PUT_LINE("in NEXT_CHARACTER");
  4152.             raise;
  4153. end NEXT_CHARACTER;
  4154. ::::::::::
  4155. next_identifier.ada
  4156. ::::::::::
  4157. separate (TOKENIZER)
  4158.  
  4159. function NEXT_IDENTIFIER return TOKEN is        -- Gets next token from input
  4160. --------------------------------------------------------------------------
  4161. -- Abstract   : This function builds the next token from the input stream.
  4162. --------------------------------------------------------------------------
  4163.  
  4164.     CURRENT_CHARACTER : CHARACTER;
  4165.     INDEX             : LINE_INDEX_RANGE;
  4166.     BUILD_A_TOKEN     : TOKEN_POINTER;
  4167.     TEMPORARY_ID      : STRING(1..LINE_INDEX_RANGE'last);
  4168.     TEMPORARY_ID_LENGTH : LINE_INDEX_RANGE := 0;
  4169.  
  4170.     function LOOK_AHEAD(CHARACTER_COUNT : in LINE_COLUMN := 1)
  4171.              return CHARACTER is
  4172.  
  4173.     begin
  4174.         if (CURRENT_LINE.COLUMN + CHARACTER_COUNT <= CURRENT_LINE.LENGTH) then
  4175.             return CURRENT_LINE.LINE(CURRENT_LINE.COLUMN + CHARACTER_COUNT);
  4176.         else return ' ';
  4177.         end if;
  4178.         exception
  4179.             when others =>
  4180.                 TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4181.                 TEXT_IO.PUT_LINE(" in LOOK_AHEAD");
  4182.                 raise;
  4183.     end LOOK_AHEAD;
  4184.  
  4185.     procedure PUSH_BACK_CHARACTER is
  4186.  
  4187.     begin
  4188.         if (CURRENT_LINE.COLUMN - 1 > 0) then
  4189.             CURRENT_LINE.COLUMN := CURRENT_LINE.COLUMN - 1;
  4190.         end if;
  4191.         exception
  4192.             when others =>
  4193.                 TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4194.                 TEXT_IO.PUT_LINE(" in PUSH_BACK_CHARACTER");
  4195.                 raise;
  4196.     end PUSH_BACK_CHARACTER;
  4197.  
  4198. begin
  4199.     BUILD_A_TOKEN := new TOKEN;
  4200.     BUILD_A_TOKEN.NEXT_TOKEN := null;
  4201.     BUILD_A_TOKEN.PREVIOUS_TOKEN := null;
  4202.     -- Set the column to the length of the current line in case END_LINE or
  4203.     -- END_FILE is raised by NEXT_CHARACTER
  4204.     if CURRENT_LINE.LENGTH > 0 then
  4205.         BUILD_A_TOKEN.TOKEN_POSITION.COLUMN := CURRENT_LINE.LENGTH - 1;
  4206.     else
  4207.         BUILD_A_TOKEN.TOKEN_POSITION.COLUMN := 0;
  4208.     end if;
  4209.     begin -- block to handle exceptions raised by NEXT_CHARACTER
  4210.         CURRENT_CHARACTER := NEXT_CHARACTER;
  4211.         while CURRENT_CHARACTER = ' ' loop
  4212.             CURRENT_CHARACTER := NEXT_CHARACTER;
  4213.         end loop;
  4214.         BUILD_A_TOKEN.TOKEN_POSITION.LINE := CURRENT_LINE_NUMBER;
  4215.         BUILD_A_TOKEN.TOKEN_POSITION.COLUMN := CURRENT_LINE.COLUMN;
  4216.         case CURRENT_CHARACTER is
  4217.             when '&' =>
  4218.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := CONCATENATION_OPERATOR;
  4219.             when ')' =>
  4220.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := RIGHT_PARENTHESIS;
  4221.             when '(' =>
  4222.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := LEFT_PARENTHESIS;
  4223.             when '+' =>
  4224.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := ADDITION_OPERATOR;
  4225.             when ',' =>
  4226.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := COMMA;
  4227.             when ';' =>
  4228.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := SEMICOLON;
  4229.             when '|' =>
  4230.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := VERTICAL_BAR;
  4231.             when '.' =>
  4232.                 if (LOOK_AHEAD = '.') then
  4233.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4234.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := DOUBLE_DOT;
  4235.                 else
  4236.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := PERIOD;
  4237.                 end if;
  4238.             when ':' =>
  4239.                 if (LOOK_AHEAD = '=') then
  4240.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4241.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := ASSIGNMENT_OPERATOR;
  4242.                 else
  4243.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := COLON;
  4244.                 end if;
  4245.             when '-' =>
  4246.                 if (LOOK_AHEAD = '-') then
  4247.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4248.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := COMMENT;
  4249.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4250.                     BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4251.                         DYN.D_STRING(CURRENT_LINE.LINE(
  4252.                         CURRENT_LINE.COLUMN..CURRENT_LINE.LENGTH));
  4253.                     CURRENT_LINE.COLUMN := CURRENT_LINE.LENGTH;
  4254.                 else
  4255.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := SUBTRACTION_OPERATOR;
  4256.                 end if;
  4257.             when '*' =>
  4258.                 if (LOOK_AHEAD = '*') then
  4259.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4260.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := EXPONENTIATE_OPERATOR;
  4261.                 else
  4262.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := MULTIPLICATION_OPERATOR;
  4263.                 end if;
  4264.             when '=' =>
  4265.                 if (LOOK_AHEAD = '>') then
  4266.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4267.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := ARROW;
  4268.                 else
  4269.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := EQUAL_OPERATOR;
  4270.                 end if;
  4271.             when '/' =>
  4272.                 if (LOOK_AHEAD = '=') then
  4273.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4274.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := INEQUAL_OPERATOR;
  4275.                 else
  4276.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := DIVISION_OPERATOR;
  4277.                 end if;
  4278.             when '>' =>
  4279.                 if (LOOK_AHEAD = '=') then
  4280.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4281.                     BUILD_A_TOKEN.TYPE_OF_TOKEN :=
  4282.                         GREATER_THAN_OR_EQUAL_OPERATOR;
  4283.                 elsif (LOOK_AHEAD = '>') then
  4284.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4285.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := RIGHT_LABEL_BRACKET;
  4286.                 else
  4287.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := GREATER_THAN_OPERATOR;
  4288.                 end if;
  4289.             when '<' =>
  4290.                 if (LOOK_AHEAD = '=') then
  4291.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4292.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := LESS_THAN_OR_EQUAL_OPERATOR;
  4293.                 elsif (LOOK_AHEAD = '>') then
  4294.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4295.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := BOX;
  4296.                 elsif (LOOK_AHEAD = '<') then
  4297.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4298.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := LEFT_LABEL_BRACKET;
  4299.                 else
  4300.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := LESS_THAN_OPERATOR;
  4301.                 end if;
  4302.             when ''' =>
  4303.                 if (LOOK_AHEAD(2) = ''') then
  4304.                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4305.                     BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4306.                         DYN.D_STRING(CURRENT_CHARACTER);
  4307.                     CURRENT_CHARACTER := NEXT_CHARACTER;-- skip tick
  4308.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := CHARACTER_LITERAL;
  4309.                 else
  4310.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := TICK;
  4311.                 end if;
  4312.             when '"' =>
  4313.                 CURRENT_CHARACTER := NEXT_CHARACTER;
  4314.                 begin   -- block to handle unexpected end of line in incorrect
  4315.                         -- input code
  4316.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := STRING_LITERAL;
  4317.                     while CURRENT_CHARACTER /= '"' loop
  4318.                         TEMPORARY_ID_LENGTH := TEMPORARY_ID_LENGTH + 1;
  4319.                         TEMPORARY_ID(TEMPORARY_ID_LENGTH) := CURRENT_CHARACTER;
  4320.                         CURRENT_CHARACTER := NEXT_CHARACTER;
  4321.                     end loop;
  4322.                     BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4323.                         DYN.D_STRING(TEMPORARY_ID(1..TEMPORARY_ID_LENGTH));
  4324.                     exception
  4325.                         when END_LINE =>
  4326.                             BUILD_A_TOKEN.TYPE_OF_TOKEN := END_OF_LINE;
  4327.                         when END_FILE =>
  4328.                             BUILD_A_TOKEN.TYPE_OF_TOKEN := END_OF_FILE;
  4329.                             BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4330.                                 DYN.D_STRING(TEXT_IO.NAME(INPUT_FILE));
  4331.                         when others =>
  4332.                             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4333.                             TEXT_IO.PUT_LINE
  4334.                                 ("in block to handle quoted string");
  4335.                             raise;
  4336.                 end;
  4337.             when 'A' .. 'Z' | 'a' .. 'z' =>
  4338.                 begin   -- block to handle end of line or end of file
  4339.                     while ((CURRENT_CHARACTER >= 'A') and
  4340.                            (CURRENT_CHARACTER <= 'Z')) or
  4341.                           ((CURRENT_CHARACTER >= 'a') and
  4342.                            (CURRENT_CHARACTER <= 'z')) or
  4343.                           ((CURRENT_CHARACTER >= '0') and
  4344.                            (CURRENT_CHARACTER <= '9')) or
  4345.                            (CURRENT_CHARACTER = '_') loop
  4346.                         TEMPORARY_ID_LENGTH := TEMPORARY_ID_LENGTH + 1;
  4347.                         TEMPORARY_ID(TEMPORARY_ID_LENGTH) := CURRENT_CHARACTER;
  4348.                         CURRENT_CHARACTER := NEXT_CHARACTER;
  4349.                     end loop;
  4350.                     if CURRENT_CHARACTER /= ' ' then
  4351.                         PUSH_BACK_CHARACTER;    -- last character not part of
  4352.                     end if;                     -- ID and not "parsed"
  4353.                     exception
  4354. --                      when END_FILE | END_LINE => null; -- ok exceptions
  4355.                         when others =>
  4356.                             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4357.                             TEXT_IO.PUT_LINE("in block to handle identifiers ");
  4358.                             raise;
  4359.                 end;
  4360.                 BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4361.                     DYN.D_STRING(TEMPORARY_ID(1..TEMPORARY_ID_LENGTH));
  4362.                 if IS_A_RESERVED_WORD(BUILD_A_TOKEN.PHYSICAL_REPRESENTATION)
  4363.                 then
  4364.                     BUILD_A_TOKEN.TYPE_OF_TOKEN :=
  4365.                         RESERVED_WORD(BUILD_A_TOKEN.PHYSICAL_REPRESENTATION);
  4366.                 else
  4367.                     BUILD_A_TOKEN.TYPE_OF_TOKEN := IDENTIFIER;
  4368.                 end if;
  4369.             when '0' .. '9' =>
  4370.                 begin   -- block to handle end of line or end of file
  4371.                     while ((CURRENT_CHARACTER >= '0') and
  4372.                            (CURRENT_CHARACTER <= '9')) or
  4373.                            (CURRENT_CHARACTER = '_') loop
  4374.                         TEMPORARY_ID_LENGTH := TEMPORARY_ID_LENGTH + 1;
  4375.                         TEMPORARY_ID(TEMPORARY_ID_LENGTH) := CURRENT_CHARACTER;
  4376.                         CURRENT_CHARACTER := NEXT_CHARACTER;
  4377.                         case CURRENT_CHARACTER is
  4378.                             when '.' =>         -- skip decimal point
  4379.                                 if (LOOK_AHEAD >= '0') and
  4380.                                    (LOOK_AHEAD <= '9') then
  4381.                                     TEMPORARY_ID_LENGTH :=
  4382.                                         TEMPORARY_ID_LENGTH + 1;
  4383.                                     TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4384.                                         CURRENT_CHARACTER;
  4385.                                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4386.                                 end if;
  4387.                             when 'E' | 'e' =>   -- skip E and optional sign
  4388.                                 TEMPORARY_ID_LENGTH := TEMPORARY_ID_LENGTH + 1;
  4389.                                 TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4390.                                     CURRENT_CHARACTER;
  4391.                                 CURRENT_CHARACTER := NEXT_CHARACTER;
  4392.                                 if (CURRENT_CHARACTER = '-') or
  4393.                                    (CURRENT_CHARACTER = '+') then
  4394.                                     TEMPORARY_ID_LENGTH :=
  4395.                                         TEMPORARY_ID_LENGTH + 1;
  4396.                                     TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4397.                                         CURRENT_CHARACTER;
  4398.                                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4399.                                 end if;
  4400.                             when '#' =>         -- based literal
  4401.                                 TEMPORARY_ID_LENGTH := TEMPORARY_ID_LENGTH + 1;
  4402.                                 TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4403.                                     CURRENT_CHARACTER;
  4404.                                 CURRENT_CHARACTER := NEXT_CHARACTER;
  4405.                                 -- There is a chance that we will skip over
  4406.                                 -- valid tokens searching for closing '#' if it
  4407.                                 -- is missing, but ill formed inpute is NOT our
  4408.                                 -- problem.
  4409.                                 while (CURRENT_CHARACTER /= '#') loop
  4410.                                     TEMPORARY_ID_LENGTH :=
  4411.                                         TEMPORARY_ID_LENGTH + 1;
  4412.                                     TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4413.                                         CURRENT_CHARACTER;
  4414.                                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4415.                                 end loop;
  4416.                                 -- Now stick # into ID and continue
  4417.                                 TEMPORARY_ID_LENGTH := TEMPORARY_ID_LENGTH + 1;
  4418.                                 TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4419.                                     CURRENT_CHARACTER;
  4420.                                 CURRENT_CHARACTER := NEXT_CHARACTER;
  4421.                                 if (CURRENT_CHARACTER = 'E') or
  4422.                                    (CURRENT_CHARACTER = 'e') then
  4423.                                                 -- skip E and optional sign
  4424.                                     TEMPORARY_ID_LENGTH :=
  4425.                                         TEMPORARY_ID_LENGTH + 1;
  4426.                                     TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4427.                                         CURRENT_CHARACTER;
  4428.                                     CURRENT_CHARACTER := NEXT_CHARACTER;
  4429.                                     if (CURRENT_CHARACTER = '-') or
  4430.                                        (CURRENT_CHARACTER = '+') then
  4431.                                         TEMPORARY_ID_LENGTH :=
  4432.                                             TEMPORARY_ID_LENGTH + 1;
  4433.                                         TEMPORARY_ID(TEMPORARY_ID_LENGTH) :=
  4434.                                             CURRENT_CHARACTER;
  4435.                                         CURRENT_CHARACTER := NEXT_CHARACTER;
  4436.                                     end if;
  4437.                                 end if;
  4438.                             when others => null;
  4439.                         end case;
  4440.                     end loop;
  4441.                     if CURRENT_CHARACTER /= ' ' then
  4442.                         PUSH_BACK_CHARACTER;    -- last character not part of
  4443.                     end if;                     -- number and not "parsed"
  4444.                     exception
  4445. --                      when END_FILE | END_LINE => null; -- ok exceptions
  4446.                         when others =>
  4447.                             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4448.                             TEXT_IO.PUT_LINE("in block to handle numeric " &
  4449.                                              "literals");
  4450.                             raise;
  4451.                 end;
  4452.                 BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4453.                     DYN.D_STRING(TEMPORARY_ID(1..TEMPORARY_ID_LENGTH));
  4454.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := NUMERIC_LITERAL;
  4455.             when others =>
  4456.                 BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4457.                     DYN.D_STRING(CURRENT_CHARACTER);
  4458.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := ANYTHING_ELSE;
  4459.         end case;
  4460.         exception
  4461.             when END_LINE =>
  4462.                 BUILD_A_TOKEN.TOKEN_POSITION.LINE := CURRENT_LINE_NUMBER - 1;
  4463.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := END_OF_LINE;
  4464.             when END_FILE =>
  4465.                 BUILD_A_TOKEN.TOKEN_POSITION.LINE := CURRENT_LINE_NUMBER;
  4466.                 BUILD_A_TOKEN.TYPE_OF_TOKEN := END_OF_FILE;
  4467.                 BUILD_A_TOKEN.PHYSICAL_REPRESENTATION :=
  4468.                     DYN.D_STRING(TEXT_IO.NAME(INPUT_FILE));
  4469.             when others =>
  4470.                 TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4471.                 TEXT_IO.PUT_LINE("in NEXT_IDENTIFIER");
  4472.                 raise;
  4473.     end;
  4474.     return BUILD_A_TOKEN.all;
  4475. end NEXT_IDENTIFIER;
  4476. ::::::::::
  4477. build_tokens.ada
  4478. ::::::::::
  4479. separate (TOKENIZER)
  4480.  
  4481. procedure BUILD_TOKENS is
  4482. --------------------------------------------------------------------------
  4483. -- Abstract   : This is the procedure that builds the token stream from
  4484. --              the input Ada source file(s).
  4485. --------------------------------------------------------------------------
  4486.  
  4487.     CURRENT_TOKEN : TOKEN_POINTER;
  4488.     LAST_TOKEN : TOKEN_POINTER;
  4489.     MORE_FILES : BOOLEAN := TRUE;
  4490. begin
  4491.     ROOT_TOKEN := null;
  4492.     LAST_TOKEN := null;
  4493.     FILE_HANDLING.INPUT_FILE_ID(INPUT_FILE,MORE_FILES);
  4494.     while MORE_FILES loop
  4495.         CURRENT_LINE_NUMBER := 0;
  4496.         CURRENT_LINE.LENGTH := 0;
  4497.         CURRENT_LINE.COLUMN := 0;
  4498.         loop
  4499.             CURRENT_TOKEN := new TOKEN;
  4500.             CURRENT_TOKEN.all := NEXT_IDENTIFIER;
  4501.             if TYPE_OF_TOKEN_IS(CURRENT_TOKEN.all) = IDENTIFIER then
  4502.                 INSERT(CURRENT_TOKEN.PHYSICAL_REPRESENTATION,ROOT);
  4503.             end if;
  4504.             if ROOT_TOKEN = null then
  4505.                 ROOT_TOKEN := CURRENT_TOKEN;
  4506.                 LAST_TOKEN := CURRENT_TOKEN;
  4507.             else
  4508.                 LAST_TOKEN.NEXT_TOKEN := CURRENT_TOKEN;
  4509.                 CURRENT_TOKEN.PREVIOUS_TOKEN := LAST_TOKEN;
  4510.                 LAST_TOKEN := CURRENT_TOKEN;
  4511.             end if;
  4512.             exit when TYPE_OF_TOKEN_IS(CURRENT_TOKEN.all) = END_OF_FILE;
  4513.         end loop;
  4514.         FILE_HANDLING.INPUT_FILE_ID(INPUT_FILE,MORE_FILES);
  4515.     end loop;
  4516.     exception
  4517.         when FILE_HANDLING.HELP_ASKED_FOR =>
  4518.             raise;
  4519.         when others =>
  4520.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4521.             TEXT_IO.PUT_LINE(" in BUILD_TOKENS");
  4522.             raise;
  4523. end BUILD_TOKENS;
  4524. ::::::::::
  4525. line_containing.ada
  4526. ::::::::::
  4527. separate (TOKENIZER)
  4528.  
  4529. procedure LINE_CONTAINING_TOKEN(CURRENT_TOKEN : in TOKEN;
  4530.                                 LINE : out DYN.DYN_STRING) is
  4531. --------------------------------------------------------------------------
  4532. -- Abstract   : This procedure builds the source line containing the input
  4533. --              token by scanning the tokens in each direction.
  4534. --------------------------------------------------------------------------
  4535. -- Parameters : CURRENT_TOKEN   - token to build line for
  4536. --              LINE            - Copy of input line
  4537. --------------------------------------------------------------------------
  4538.     RETURN_STRING : LINE_STRING := (1..LINE_STRING'length => ' ');
  4539.     STRING_LENGTH : LINE_INDEX_RANGE := 0;
  4540.     CUR_TOKEN     : TOKEN;
  4541. begin
  4542.     CUR_TOKEN := CURRENT_TOKEN;
  4543.     -- get to the token that ends the line before the line containing this token
  4544.     -- block to encapsulate PREVIOUS_TOKEN calls in case this is the first
  4545.     -- line of the source file
  4546.     begin
  4547.         while CUR_TOKEN.TOKEN_POSITION.LINE = CURRENT_TOKEN.TOKEN_POSITION.LINE
  4548.             loop
  4549.             CUR_TOKEN := PREVIOUS_TOKEN(CUR_TOKEN);
  4550.         end loop;
  4551.         CUR_TOKEN := NEXT_TOKEN(CUR_TOKEN);
  4552.         exception
  4553.             when END_OF_TOKENS =>               -- will be raised if this is 1st
  4554.                 null;                           -- line
  4555.             when others => raise;
  4556.     end;
  4557.     -- CUR_TOKEN should now point to the first token of the line
  4558.     while (TYPE_OF_TOKEN_IS(CUR_TOKEN) /= END_OF_LINE) and
  4559.          (TYPE_OF_TOKEN_IS(CUR_TOKEN) /= END_OF_FILE) loop
  4560.         RETURN_STRING(CUR_TOKEN.TOKEN_POSITION.COLUMN ..
  4561.             (CUR_TOKEN.TOKEN_POSITION.COLUMN - 1) +
  4562.             DYN.LENGTH(EXTERNAL_REPRESENTATION(CUR_TOKEN))) :=
  4563.             DYN.STR(EXTERNAL_REPRESENTATION(CUR_TOKEN));
  4564.         STRING_LENGTH := (CUR_TOKEN.TOKEN_POSITION.COLUMN - 1) +
  4565.             DYN.LENGTH(EXTERNAL_REPRESENTATION(CUR_TOKEN));
  4566.         CUR_TOKEN := NEXT_TOKEN(CUR_TOKEN);
  4567.     end loop;
  4568.     LINE := DYN.D_STRING(RETURN_STRING(1..STRING_LENGTH));
  4569.     exception
  4570.         when others =>
  4571.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4572.             TEXT_IO.PUT_LINE(" in LINE_CONTAINING_TOKEN");
  4573.             raise;
  4574. end LINE_CONTAINING_TOKEN;
  4575. ::::::::::
  4576. tree_root.ada
  4577. ::::::::::
  4578. separate (TOKENIZER)
  4579.  
  4580. function TREE_ROOT return IDENTIFIER_TREE is
  4581. --------------------------------------------------------------------------
  4582. -- Abstract   : This function returns the root of the binary tree created
  4583. --              by the tokenizer
  4584. --------------------------------------------------------------------------
  4585.  
  4586. begin
  4587.     return ROOT;
  4588.     exception
  4589.         when others =>
  4590.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  4591.             TEXT_IO.PUT_LINE(" in TREE_ROOT");
  4592.             raise;
  4593. end TREE_ROOT;
  4594. ::::::::::
  4595. sparam_body.ada
  4596. ::::::::::
  4597. Package body Style_Parameters is
  4598.     use TOKENIZER;
  4599.  
  4600.    type Package_Name_Node;
  4601.    type Package_List     is access Package_Name_node;
  4602.    type Package_Name_Node is
  4603.          record
  4604.            P_Name : DYN.DYN_STRING;
  4605.            Next   : Package_List;
  4606.          end record;
  4607.  
  4608.    ERRORS_TO_LIST : Natural := 5;
  4609.    KEYWORD_OUTPUT : Keyword_Options := None;
  4610.    OPERATOR_OUTPUT: boolean;
  4611.  
  4612.    SHORT_PROGRAM : Natural   := 100;    -- Any program this length or shorter
  4613.                                         -- may ignore limits when checking
  4614.                                         -- complexity, keyword frequency,
  4615.                                         -- etc.
  4616.  
  4617.  
  4618.    SHORT_WORD : Word_Lengths := 6;      -- Any word this length or shorter
  4619.                                         -- may ignore Limits when checking
  4620.                                         -- underscores and vowels.
  4621.  
  4622.    SHORT_STRUCTURE : Natural := 5;      -- Any structure this length or shorter
  4623.                                         -- may ignore style when checking for
  4624.                                         -- surrounding blank lines or
  4625.                                         -- loop names.
  4626.  
  4627.    RESERVED_CASE : Reserve_Word_Cases := Reserved_Case_Lower;
  4628.  
  4629.    OBJECT_CASE : Object_Name_Cases := Name_Case_Upper;
  4630.  
  4631.    NAME_LENGTH_AVE : Word_Lengths range 1..Word_Lengths'last := 5;
  4632.  
  4633.    UNDERSCORE_REQUIRED : boolean;
  4634.    UNDERSCORE_LENGTH_AVE : Word_Lengths range 1..Word_Lengths'last
  4635.           := Name_Length_Ave;
  4636.  
  4637.    ABBREV_AVE : Abbreviation_Aves := 0.35;
  4638.    SPELLING_REQUIREMENT : Require_Type := Not_Required;
  4639.  
  4640. -- Physical Layout
  4641.    ONE_LINE_PER_STATEMENT  : boolean;
  4642.   -- Indentation
  4643.   -- Initial on line    is Always Required!  No parameter!
  4644.    TYPE_INDENTATION        : boolean;
  4645.    COMMENT_INDENTATION     : boolean;
  4646.   -- Blank Space
  4647.    BLANKS_AROUND_BLOCKS    : boolean;
  4648.    BLANK_LINE_PERCENT      : float     := 0.20;
  4649.    PROLOG_NEEDED           : boolean;
  4650.    LOOP_NAME_NEEDED        : Loop_Names_Needs;
  4651.    LOOP_NAME_PERCENT       : float     := 0.30; -- 30% of loops have names.
  4652.  
  4653. -- Statement USE
  4654.    KEYWRD_ARRAY            : Keyword_Uses;
  4655.    AVE_SIZE_OF_COMMENT     : Positive  := 15;   -- Average chars/comment
  4656.  
  4657. -- Information hiding, abstraction, data use
  4658.   -- constants/literals in code vs. specification
  4659.    LITERAL_FREQ_IN_BODY    : Float     := 0.10; -- 90% should be in spec.
  4660.   -- Should declare own types
  4661.    UNIVERSAL_TYPE_USAGE    : Float    := 0.40;  -- Just a WAG
  4662.   -- Should use enumeration and record facilities
  4663.    DATA_STRUCTURE_USE      : boolean  := TRUE;   -- Do we check for structures?
  4664.    ATTRIBUTE_USE           : Require_Type := Required; -- or attributes?
  4665.  
  4666. -- Modularity
  4667.    LOWER_PARAMETER_SIZE    : Natural  := 1;
  4668.    UPPER_PARAMETER_SIZE    : Natural  := 8;
  4669.    LOWER_SUBPROGRAM_SIZE   : Natural  := 10;
  4670.    UPPER_SUBPROGRAM_SIZE   : Natural  := 200;
  4671.  
  4672. -- Complexity
  4673.    KEYWORD_TYPES_USED      : float     := 0.65; -- This applies when program
  4674.                                                 -- is not 'short'.  # keywords
  4675.                                                 -- is Number_of_Keywords;
  4676.    CONTROL_NESTING_LIMIT   : Natural   := 8;
  4677.    SUBPROGRAM_NESTING_LIMIT: Natural   := 4;
  4678.    PACKAGE_NESTING_LIMIT   : Natural   := 2;
  4679.    MAX_LOOP_EXITS          : Natural   := 1;    -- Structured programming df
  4680.    LINE_SIZE_LIMIT         : Positive  := 80;
  4681.    CHAR_SET_ALLOWED        : Character_Set_Types := Graphic;
  4682.    REP_SPECS_PERMITTED     : boolean   := TRUE;
  4683.    ADDR_CLAUSES_PERMITTED  : boolean   := TRUE;
  4684.    PRAGMAS_TO_BE_NOTED     : Pragma_Classes := System_Dependent;
  4685.    PROSCRIBED : constant array (1.. 5) of DYN.DYN_STRING :=
  4686.         (DYN.D_STRING("SYSTEM"),
  4687.         DYN.D_STRING("TTY_IO"),
  4688.         DYN.D_STRING("UNCHECKED_CONVERSION"),
  4689.         DYN.D_STRING("UNCHECKED_DEALLOCATION"),
  4690.         DYN.D_STRING("CURRENT_EXCEPTION"));
  4691.  
  4692. -------------------------------------
  4693. -- This procedure obtains the 'style
  4694. -------------------------------------
  4695.   Procedure Set_Style_Parameters is
  4696.           -- This sets the parameter variables
  4697.     TEMP_PACKAGE : Package_List;
  4698.     END_OF_PACKAGE_LIST : Package_List;
  4699.     KWD_DEFAULT  : Keyword_Use_Descript
  4700.                  := (Use_Class => Free_Use,
  4701.                      Use_Freq  => 0.0);
  4702.   begin
  4703.     ERRORS_TO_LIST  := 10;
  4704.     KEYWORD_OUTPUT  :=   Used;
  4705.     OPERATOR_OUTPUT :=   FALSE;
  4706.     SHORT_PROGRAM   := 100;
  4707.     SHORT_WORD      :=   6;
  4708.     SHORT_STRUCTURE :=   5;
  4709.     RESERVED_CASE   := Reserved_Case_Lower;
  4710.     OBJECT_CASE     := Name_Case_Upper;
  4711.     NAME_LENGTH_AVE := 5;
  4712.     UNDERSCORE_REQUIRED := TRUE;
  4713.     UNDERSCORE_LENGTH_AVE := 5;
  4714.     ABBREV_AVE      := 0.35;
  4715.     SPELLING_REQUIREMENT := Not_Required;
  4716.     ONE_LINE_PER_STATEMENT := TRUE;
  4717.     TYPE_INDENTATION := TRUE;
  4718.     COMMENT_INDENTATION := FALSE;
  4719.     BLANKS_AROUND_BLOCKS := TRUE;
  4720.     LOOP_NAME_NEEDED := Required;
  4721.     LOOP_NAME_PERCENT := 0.30;
  4722.     AVE_SIZE_OF_COMMENT := 15;
  4723.     LITERAL_FREQ_IN_BODY := 0.30;
  4724.     UNIVERSAL_TYPE_USAGE := 0.40;
  4725.     DATA_STRUCTURE_USE := TRUE;
  4726.     ATTRIBUTE_USE := Required;
  4727.     LOWER_PARAMETER_SIZE := 0;
  4728.     UPPER_PARAMETER_SIZE := 4;
  4729.     LOWER_SUBPROGRAM_SIZE := 10;
  4730.     UPPER_SUBPROGRAM_SIZE := 200;
  4731.     CONTROL_NESTING_LIMIT := 8;
  4732.     SUBPROGRAM_NESTING_LIMIT := 4;
  4733.     PACKAGE_NESTING_LIMIT := 2;
  4734.     MAX_LOOP_EXITS           := 1;    -- Structured programming df
  4735.     LINE_SIZE_LIMIT         := 80;
  4736.     CHAR_SET_ALLOWED       := Graphic;
  4737.     REP_SPECS_PERMITTED      := FALSE;
  4738.     ADDR_CLAUSES_PERMITTED   := FALSE;
  4739. --    KEYWRD_ARRAY := TBD;
  4740.     For kwd in TOKENIZER.KEYWORDS loop
  4741.       KEYWRD_ARRAY(kwd) := KWD_DEFAULT;
  4742.     end loop;
  4743.     KEYWRD_ARRAY( TOKENIZER.KEYWORDS'(TOKENIZER.GOTO_TOKEN) ):=
  4744.       (Use_Class => No_Use,         Use_Freq => 0.00);
  4745.     KEYWRD_ARRAY( TOKENIZER.USE_TOKEN ) :=
  4746.       (Use_Class => Restricted_Use, Use_Freq => 0.20);
  4747.  
  4748.     PRAGMAS_TO_BE_NOTED := All_Pragmas;
  4749.  
  4750. --    Set of the LIST of PROSCRIBED ('bad') PACKAGES
  4751. --    These packages are defined by the constant array PROSCRIBED, above.
  4752. --    To change the proscribed packages, change that array.
  4753.  
  4754.   end;
  4755.  
  4756. --------------------------------------------
  4757. -- These return style individual parameters
  4758. --------------------------------------------
  4759.   function Number_of_Errors_to_Report return natural is
  4760.   -- This returns a number telling how many times to list
  4761.   -- a error in the "Flaws" output.  I.E. If this returns
  4762.   -- "3", then only the first three occurences of each
  4763.   -- type of error are listed.
  4764.   begin
  4765.     return ERRORS_TO_LIST;
  4766.   end;
  4767.  
  4768.   function OUTPUT_KEYWORD_LIST return Keyword_Options is
  4769.   -- This function returns a value specifying the output format for
  4770.   -- listing the reserved word usage.  It specifys which class of
  4771.   -- reserved words to output, all keywords, only those keywords
  4772.   -- used or not used, keywords used in violation of style restrictions,
  4773.   -- or no keywords output.
  4774.   begin
  4775.     return KEYWORD_OUTPUT;
  4776.   end;
  4777.  
  4778.   function OUTPUT_OPERATOR_LIST return boolean is
  4779.   -- This function returns true if the operator list is to be printed
  4780.   -- as part of the style report.
  4781.   begin
  4782.     return OPERATOR_OUTPUT;
  4783.   end;
  4784.  
  4785.   function SMALL_PROGRAM_SIZE return natural is
  4786.   -- returns size of programs considered 'too small' so limits of
  4787.   -- some things may be violated with not penalty.
  4788.   begin
  4789.     return SHORT_PROGRAM;
  4790.   end;
  4791.  
  4792.   function Small_Word_Size    return Word_Lengths is
  4793.   -- returns size of words considered 'too small' so limits of
  4794.   -- some things may be violated with no penalty.
  4795.   begin
  4796.     return SHORT_WORD;
  4797.   end;
  4798.  
  4799.   function Small_Structure_Size    return Natural is
  4800.   -- returns size (in statements) of structures considered 'too small' so
  4801.   -- some constraints may be violated with no penalty.
  4802.   begin
  4803.     return SHORT_STRUCTURE;
  4804.   end;
  4805.  
  4806.   function Case_of_Reserved_Words return Reserve_Word_Cases is
  4807.   begin
  4808.     return RESERVED_CASE;
  4809.   end;
  4810.  
  4811.   function Case_of_Object_Names return Object_Name_Cases is
  4812.   begin
  4813.     return OBJECT_CASE;
  4814.   end;
  4815.  
  4816.   function Average_Name_Size  return Word_Lengths is
  4817.   -- The average size of names in the program should be greater than
  4818.   -- this minimum.
  4819.   begin
  4820.     return NAME_LENGTH_AVE;
  4821.   end;
  4822.  
  4823.   function Is_Underscore_Required return boolean is
  4824.   begin
  4825.     return UNDERSCORE_REQUIRED;
  4826.   end;
  4827.  
  4828.   function Average_Underscore_Size return Word_Lengths is
  4829.   -- If underscores are required and the word under inspection is
  4830.   -- longer than a "Small_Word", then the parts separated by
  4831.   -- underscores should be longer than this minimum.
  4832.   begin
  4833.     return UNDERSCORE_LENGTH_AVE;
  4834.   end;
  4835.  
  4836.   function Vowel_Frequency return float is
  4837.   -- To keep people from abbreviating too much, check the percentage of
  4838.   -- vowels to consonants.  If (Vowel / Total-letters) is less than
  4839.   -- Vowel_Frequency percent, there is something wrong.
  4840.   begin
  4841.     return ABBREV_AVE;
  4842.   end;
  4843.   function SPELLING_REQUIRED return Require_Type is
  4844.   -- This function returns 'Required' if the style checker is to
  4845.   -- send words to a spelling checker to validate variable names.
  4846.   begin
  4847.     return SPELLING_REQUIREMENT;
  4848.   end;
  4849.  
  4850.   function Is_One_Statement_per_line_Required return boolean is
  4851.   begin
  4852.     return ONE_LINE_PER_STATEMENT;
  4853.   end;
  4854.   function Is_Declaration_Indentation_Required return boolean is
  4855.   -- Forced to indent properly on object, type declarations?
  4856.   begin
  4857.     return TYPE_INDENTATION;
  4858.   end;
  4859.   function Is_Comment_Indentation_Required return boolean is
  4860.   -- Forced to indent the trailing comments after statement on a line?
  4861.   begin
  4862.     return COMMENT_INDENTATION;
  4863.   end;
  4864.  
  4865.   function Is_Blank_Lines_around_Blocks_Required return boolean is
  4866.   -- Should blank lines around blocks, loops, etc. be required?
  4867.   begin
  4868.     return BLANKS_AROUND_BLOCKS;
  4869.   end;
  4870. --  I think we deleted this function!
  4871. --      function Average_Blank_Lines return float is
  4872. --      -- The average # of blank lines should be 'Ave-blank-lines' +- delta
  4873. --      -- for readability's sake
  4874. --        begin
  4875. --          return ;
  4876. --        end;
  4877.  
  4878.   function Loop_Name_Required return Loop_Names_Needs is
  4879.   -- Are loop-names necessary, should loops of a certain size need names.
  4880.   begin
  4881.     return LOOP_NAME_NEEDED;
  4882.   end;
  4883.  
  4884.   procedure Reserved_Word_Info ( Usage : out Keyword_Uses ) is
  4885.   begin
  4886.     Usage := KEYWRD_ARRAY;
  4887.   end;
  4888.  
  4889.   function Average_Comment_Size return positive is
  4890.   -- To prevent style "tricking" comments must have a minimum average
  4891.   -- size;
  4892.   begin
  4893.     return AVE_SIZE_OF_COMMENT;
  4894.   end;
  4895.  
  4896.   function Average_Literal_in_Body return float is
  4897.   -- Literals should be in the declaration rather then the body, so
  4898.   -- the number of literals in the body should be less than "ave-literal"
  4899.   begin
  4900.     return LITERAL_FREQ_IN_BODY;
  4901.   end;
  4902.  
  4903.   function Average_Universal_Usage return float is
  4904.   -- In general, good use should be made of programmer-defined types
  4905.   -- rather than universal integer, float, etc.  The percentage of
  4906.   -- types which are universal integer, float, natural, positive, etc.
  4907.   -- should be less then "ave-universals"
  4908.   begin
  4909.     return UNIVERSAL_TYPE_USAGE;
  4910.   end;
  4911.  
  4912.   function Is_Data_Structure_Use_Required return boolean is
  4913.   -- Should we check for enumeration types, records?
  4914.   begin
  4915.     return DATA_STRUCTURE_USE;
  4916.   end;
  4917.  
  4918.   function ATTRIBUTE_CHECK return Require_Type is
  4919.   -- This function tells whether the style checker notes the
  4920.   -- use of attributes.
  4921.   begin
  4922.     return ATTRIBUTE_USE;
  4923.   end;
  4924.  
  4925.   procedure Average_Subprogram_Size (SMALL_LIMIT : out Natural;
  4926.                                      LARGE_LIMIT : out Natural ) is
  4927.   begin
  4928.      SMALL_LIMIT := LOWER_SUBPROGRAM_SIZE;
  4929.      LARGE_LIMIT := UPPER_SUBPROGRAM_SIZE;
  4930.   end AVERAGE_SUBPROGRAM_SIZE;
  4931.  
  4932.   procedure SUBPROGRAM_PARAMETERS (SMALL_LIMIT : out Natural;
  4933.                                    LARGE_LIMIT : out Natural ) is
  4934.   begin
  4935.      SMALL_LIMIT := LOWER_PARAMETER_SIZE;
  4936.      LARGE_LIMIT := UPPER_PARAMETER_SIZE;
  4937.   end SUBPROGRAM_PARAMETERS;
  4938.  
  4939.  
  4940.   function CONTROL_NESTING_LEVEL return natural is
  4941.   -- This is the expected depth of nesting of control structures.
  4942.   begin
  4943.     return CONTROL_NESTING_LIMIT;
  4944.   end;
  4945.  
  4946.   function PACKAGE_NESTING_LEVEL return natural is
  4947.   -- This is the expected depth of nesting of packages.
  4948.   begin
  4949.     return PACKAGE_NESTING_LIMIT;
  4950.   end;
  4951.  
  4952.   function SUBPROGRAM_NESTING_LEVEL return natural is
  4953.   -- This is the expected depth of nesting of subprograms.
  4954.   begin
  4955.     return SUBPROGRAM_NESTING_LIMIT;
  4956.   end;
  4957.  
  4958.   function NUMBER_OF_LOOP_EXITS return natural is
  4959.   -- This number is a limit on the number of exits from a loop.
  4960.   begin
  4961.     return MAX_LOOP_EXITS;
  4962.   end;
  4963.  
  4964.   function LINE_SIZE return natural is
  4965.   -- This number is a limit on the number of characters in a line.
  4966.   begin
  4967.     return LINE_SIZE_LIMIT;
  4968.   end;
  4969.  
  4970.   function CHARACTER_SET return Character_Set_Types is
  4971.   -- This enumeration type determines the characters which are
  4972.   -- not flagged as style errors.  This is to limit use of
  4973.   -- graphic or extended characters which may not transport to
  4974.   -- other machines.
  4975.   begin
  4976.     return CHAR_SET_ALLOWED;
  4977.   end;
  4978.  
  4979.   function REPRESENTATION_SPECS_ALLOWED return boolean is
  4980.   -- This returns true if rep specs are allowed in the style.
  4981.   begin
  4982.     return REP_SPECS_PERMITTED;
  4983.   end;
  4984.  
  4985.   function ADDRESS_CLAUSE_ALLOWED return boolean is
  4986.   -- This returns true if address clauses are allowed in the style.
  4987.   begin
  4988.     return ADDR_CLAUSES_PERMITTED;
  4989.   end;
  4990.  
  4991.   function NOTE_PRAGMAS return Pragma_Classes is
  4992.   -- This is an enumeration type defining which pragmas (all, system-
  4993.   -- dependent, or none) are illegal as defined in the style
  4994.   begin
  4995.     return PRAGMAS_TO_BE_NOTED;
  4996.   end;
  4997.  
  4998.   function DYN_EQUAL(STR1 : in DYN.DYN_STRING;STR2: in DYN.DYN_STRING)
  4999.     return boolean is
  5000.   begin
  5001.     if DYN.LENGTH(STR1) = DYN.LENGTH(STR2) then
  5002.         return DYN.STR(STR1) = DYN.STR(STR2);
  5003.     else
  5004.         return false;
  5005.     end if;
  5006.   end DYN_EQUAL;
  5007.  
  5008.  
  5009.   function IS_A_PREDEFINED_PRAGMA (NAME : in DYN.DYN_STRING ) return boolean is
  5010.   -- This returns true if the input name is a predefined pragma as listed
  5011.   -- in the LRM appendix B.
  5012.     PRAGMA_PREDEFINED : constant array (1..14) of DYN.DYN_STRING :=
  5013.         (DYN.D_STRING("CONTROLLED"),
  5014.         DYN.D_STRING("ELABORATE"),
  5015.         DYN.D_STRING("INLINE"),
  5016.         DYN.D_STRING("INTERFACE"),
  5017.         DYN.D_STRING("LIST"),
  5018.         DYN.D_STRING("MEMORY_SIZE"),
  5019.         DYN.D_STRING("OPTIMIZE"),
  5020.         DYN.D_STRING("PACK"),
  5021.         DYN.D_STRING("PAGE"),
  5022.         DYN.D_STRING("PRIORITY"),
  5023.         DYN.D_STRING("SHARED"),
  5024.         DYN.D_STRING("STORAGE_UNIT"),
  5025.         DYN.D_STRING("SUPPRESS"),
  5026.         DYN.D_STRING("SYSTEM_NAME") );
  5027.  
  5028.     begin
  5029.        for I in PRAGMA_PREDEFINED'FIRST..PRAGMA_PREDEFINED'LAST loop
  5030.            if DYN_EQUAL( NAME, PRAGMA_PREDEFINED(I)) then
  5031.                return true;
  5032.            end if;
  5033.        end loop;
  5034.        return false;
  5035.     end IS_A_PREDEFINED_PRAGMA;
  5036.  
  5037.  
  5038.   function IS_A_PROSCRIBED_PACKAGE (NAME : in DYN.DYN_STRING) return boolean is
  5039.   -- This returns true if the input name is a package on the
  5040.   -- list of 'stylistically incorrect' packages as defined by the style.
  5041.  
  5042.     begin
  5043.        for I in PROSCRIBED'FIRST..PROSCRIBED'LAST loop
  5044.            if DYN_EQUAL(NAME, PROSCRIBED(I) ) then
  5045.                return true;
  5046.            end if;
  5047.        end loop;
  5048.        return false;
  5049.   end IS_A_PROSCRIBED_PACKAGE;
  5050.  
  5051.  
  5052. begin
  5053.     Set_Style_Parameters;
  5054.  
  5055.  
  5056. end Style_Parameters;
  5057. ::::::::::
  5058. repgen_body.ada
  5059. ::::::::::
  5060. with CURRENT_EXCEPTION;
  5061. package body REPORT_GENERATOR is
  5062. --------------------------------------------------------------------------
  5063. -- Abstract   : This is the package body for all the report routines.
  5064. --------------------------------------------------------------------------
  5065.  
  5066.     ERROR_OCCURRENCE_COUNT : array (ERRORS) of NATURAL :=
  5067.                              (ERRORS'FIRST .. ERRORS'LAST => 0);
  5068.  
  5069.     ADA_SPECIFICS_USED     : BOOLEAN := FALSE;
  5070.  
  5071.     procedure PUT_FLAW(TO_THIS : in TEXT_IO.FILE_TYPE;
  5072.                        BAD_TOKEN : in TOKENIZER.TOKEN;
  5073.                        ERROR_MESSAGE : in DYN.DYN_STRING;
  5074.                        ERROR_TYPE : in ERRORS := OTHER) is
  5075. --------------------------------------------------------------------------
  5076. -- Abstract   : This routine adds a flaw to the flaws listing file.
  5077. --------------------------------------------------------------------------
  5078. -- Parameters : TO_THIS         - File of Flaws list
  5079. --              BAD_TOKEN       - Token that points out the flaw
  5080. --              ERROR_MESSAGE   - The error message
  5081. --              ERROR_TYPE      - The type of the error
  5082. --------------------------------------------------------------------------
  5083.  
  5084.  
  5085.         BAD_LINE : DYN.DYN_STRING;
  5086.  
  5087.     begin
  5088.         ERROR_OCCURRENCE_COUNT(ERROR_TYPE) :=
  5089.             ERROR_OCCURRENCE_COUNT(ERROR_TYPE) + 1;
  5090.         if (ERROR_OCCURRENCE_COUNT(ERROR_TYPE) <=
  5091.             STYLE_PARAMETERS.NUMBER_OF_ERRORS_TO_REPORT) or
  5092.            (ERROR_TYPE > NON_STANDARD_PRAGMA_USED) then
  5093.             TOKENIZER.LINE_CONTAINING_TOKEN(BAD_TOKEN,BAD_LINE);
  5094.             TEXT_IO.PUT_LINE(TO_THIS,DYN.STR(BAD_LINE));
  5095.             TEXT_IO.PUT_LINE(TO_THIS,DYN.STR(ERROR_MESSAGE));
  5096.             TEXT_IO.NEW_LINE(TO_THIS);
  5097.         end if;
  5098.     end PUT_FLAW;
  5099.  
  5100.     procedure PUT_FLAW(TO_THIS : in TEXT_IO.FILE_TYPE;
  5101.                        BAD_TOKEN : in TOKENIZER.TOKEN;
  5102.                        ERROR_MESSAGE : in STRING;
  5103.                        ERROR_TYPE : in ERRORS := OTHER) is
  5104. --------------------------------------------------------------------------
  5105. -- Abstract   : This routine adds a flaw to the flaws listing file.
  5106. --------------------------------------------------------------------------
  5107. -- Parameters : TO_THIS         - File of Flaws list
  5108. --              BAD_TOKEN       - Token that points out the flaw
  5109. --              ERROR_MESSAGE   - The error message
  5110. --              ERROR_TYPE      - The type of the error
  5111. --------------------------------------------------------------------------
  5112.  
  5113.         BAD_LINE : DYN.DYN_STRING;
  5114.  
  5115.     begin
  5116.         ERROR_OCCURRENCE_COUNT(ERROR_TYPE) :=
  5117.             ERROR_OCCURRENCE_COUNT(ERROR_TYPE) + 1;
  5118.         if (ERROR_OCCURRENCE_COUNT(ERROR_TYPE) <=
  5119.             STYLE_PARAMETERS.NUMBER_OF_ERRORS_TO_REPORT) or
  5120.            (ERROR_TYPE > NON_STANDARD_PRAGMA_USED) then
  5121.             TOKENIZER.LINE_CONTAINING_TOKEN(BAD_TOKEN,BAD_LINE);
  5122.             TEXT_IO.PUT_LINE(TO_THIS,DYN.STR(BAD_LINE));
  5123.             TEXT_IO.PUT_LINE(TO_THIS,ERROR_MESSAGE);
  5124.             TEXT_IO.NEW_LINE(TO_THIS);
  5125.         end if;
  5126.     end PUT_FLAW;
  5127.  
  5128.     procedure GENERATE_REPORT(FROM_THIS : in REPORT_RECORD;
  5129.                               TO_THIS : in TEXT_IO.FILE_TYPE;
  5130.                               FILE_NAME : in DYN.DYN_STRING ) is
  5131.  
  5132. --------------------------------------------------------------------------
  5133. -- Abstract   : This routine generates the final error report for the
  5134. --              Style_Checker.
  5135. --------------------------------------------------------------------------
  5136. -- Parameters : FROM_THIS       - Record of errors
  5137. --              TO_THIS         - Output file
  5138. --              FILE_NAME       - Name of input file
  5139. --------------------------------------------------------------------------
  5140.     use STYLE_PARAMETERS;
  5141.  
  5142.         package NATURAL_IO is new TEXT_IO.INTEGER_IO(NATURAL);
  5143.         package MY_FLOAT_IO is new TEXT_IO.FLOAT_IO(FLOAT);
  5144.  
  5145.         -- Column constants
  5146.         DECIMAL_POINT_COLUMN    : constant NATURAL := 58;
  5147.         ERROR_FLAG_COLUMN       : constant NATURAL := 3;
  5148.         FIRST_COLUMN_START      : constant NATURAL := 7;
  5149.         SECOND_COLUMN_START     : constant NATURAL := 44;
  5150.         THIRD_COLUMN_START      : constant NATURAL := 64;
  5151.  
  5152.  
  5153.  
  5154.         -- String constants used again and again
  5155.         ACTUAL          : constant STRING := "Actual";
  5156.         ASTERIK         : constant STRING := "*";
  5157.         CHARACTERS      : constant STRING := "Characters";
  5158.         COMMENTS        : constant STRING := "Comments";
  5159.         DESIRED         : constant STRING := "Desired";
  5160.         DOT_DOT         : constant STRING := "..";
  5161.         ERRORS          : constant STRING := "Errors";
  5162.         EXCEEDED        : constant STRING := "Exceeded";
  5163.         EXCLAMATION     : constant STRING := "!";
  5164.         GREATER_THAN    : constant CHARACTER := '>';
  5165.         HEADER_LINE     : constant STRING(1 .. 74) := (1 .. 74 => '-');
  5166.         INSTANCES       : constant STRING := "Instances";
  5167.         LESS_THAN       : constant CHARACTER := '<';
  5168.         MAXIMUM         : constant STRING := "Maximum";
  5169.         PARAMETERS      : constant STRING := "Parameters";
  5170.         PERCENT         : constant STRING := "%";
  5171.         STATEMENTS      : constant STRING := "Statements";
  5172.  
  5173.         ASCII_IMAGE     : STRING(1..5);
  5174.         COLUMN          : POSITIVE;
  5175.         KEYWORD_COUNT   : NATURAL := 0;
  5176.         type KEYWORD_PERCENTAGE_ARRAY is array(TOKENIZER.TOKEN_TYPE) of FLOAT;
  5177.         KEYWORD_PERCENTAGES     : KEYWORD_PERCENTAGE_ARRAY :=
  5178.             (TOKENIZER.TOKEN_TYPE'FIRST .. TOKENIZER.TOKEN_TYPE'LAST => 0.0);
  5179.  
  5180.     procedure PUT_REPORT_LINE(INDENTION         : in NATURAL;
  5181.                               HEADER            : in STRING;
  5182.                               ASTERIK_NEEDED    : in BOOLEAN := FALSE;
  5183.                               EXCLAMATION_NEEDED: in BOOLEAN := FALSE) is
  5184.  
  5185.     begin
  5186.         if ASTERIK_NEEDED then
  5187.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5188.             TEXT_IO.PUT(TO_THIS,ASTERIK);
  5189.         elsif EXCLAMATION_NEEDED then
  5190.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5191.             TEXT_IO.PUT(TO_THIS,EXCLAMATION);
  5192.         end if;
  5193.         if INDENTION > 0 then
  5194.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(INDENTION));
  5195.         end if;
  5196.         TEXT_IO.PUT_LINE(TO_THIS,HEADER);
  5197.     exception
  5198.         when others =>
  5199.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  5200.             TEXT_IO.PUT_LINE(" in PUT_REPORT_LINE(for HEADER)");
  5201.             raise;
  5202.     end PUT_REPORT_LINE;
  5203.  
  5204.     procedure PUT_REPORT_LINE(INDENTION         : in NATURAL;
  5205.                               STYLE_ISSUE       : in STRING;
  5206.                               SUB_HEADING       : in STRING;
  5207.                               LEAD_IN           : in CHARACTER;
  5208.                               COUNT             : in NATURAL;
  5209.                               UNITS             : in STRING;
  5210.                               ASTERIK_NEEDED    : in BOOLEAN := FALSE;
  5211.                               EXCLAMATION_NEEDED: in BOOLEAN := FALSE) is
  5212.  
  5213.         COLUMN          : POSITIVE;
  5214.  
  5215.     begin
  5216.         if ASTERIK_NEEDED then
  5217.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5218.             TEXT_IO.PUT(TO_THIS,ASTERIK);
  5219.         elsif EXCLAMATION_NEEDED then
  5220.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5221.             TEXT_IO.PUT(TO_THIS,EXCLAMATION);
  5222.         end if;
  5223.         if INDENTION > 0 then
  5224.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(INDENTION));
  5225.         end if;
  5226.         TEXT_IO.PUT(TO_THIS,STYLE_ISSUE);
  5227.         if SUB_HEADING /= "" then
  5228.             TEXT_IO.SET_COL(TO_THIS,
  5229.                 TEXT_IO.POSITIVE_COUNT(SECOND_COLUMN_START));
  5230.             TEXT_IO.PUT(TO_THIS,SUB_HEADING);
  5231.         end if;
  5232.         if (COUNT < 10) then
  5233.             COLUMN := DECIMAL_POINT_COLUMN - 2;
  5234.         elsif (COUNT < 100)
  5235.             then COLUMN := DECIMAL_POINT_COLUMN - 3;
  5236.         elsif (COUNT < 1000)
  5237.             then COLUMN := DECIMAL_POINT_COLUMN - 4;
  5238.         else COLUMN := DECIMAL_POINT_COLUMN - 5;
  5239.         end if;
  5240.         TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(COLUMN));
  5241.         TEXT_IO.PUT(TO_THIS,LEAD_IN);
  5242.         NATURAL_IO.PUT(TO_THIS,COUNT,0);
  5243.         TEXT_IO.SET_COL(TO_THIS,
  5244.             TEXT_IO.POSITIVE_COUNT(THIRD_COLUMN_START));
  5245.         if (COUNT = 1) and (UNITS /= "") then
  5246.             TEXT_IO.PUT_LINE(TO_THIS,UNITS(1..UNITS'LENGTH - 1));
  5247.         else
  5248.             TEXT_IO.PUT_LINE(TO_THIS,UNITS);
  5249.         end if;
  5250.     exception
  5251.         when others =>
  5252.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  5253.             TEXT_IO.PUT_LINE(" in PUT_REPORT_LINE(for INTEGER)");
  5254.             raise;
  5255.     end PUT_REPORT_LINE;
  5256.  
  5257.     procedure PUT_REPORT_LINE(INDENTION         : in NATURAL;
  5258.                               STYLE_ISSUE       : in STRING;
  5259.                               SUB_HEADING       : in STRING;
  5260.                               LEAD_IN           : in CHARACTER;
  5261.                               COUNT             : in FLOAT;
  5262.                               UNITS             : in STRING;
  5263.                               ASTERIK_NEEDED    : in BOOLEAN := FALSE;
  5264.                               EXCLAMATION_NEEDED: in BOOLEAN := FALSE) is
  5265.  
  5266.         COLUMN          : POSITIVE;
  5267.  
  5268.     begin
  5269.         if ASTERIK_NEEDED then
  5270.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5271.             TEXT_IO.PUT(TO_THIS,ASTERIK);
  5272.         elsif EXCLAMATION_NEEDED then
  5273.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5274.             TEXT_IO.PUT(TO_THIS,EXCLAMATION);
  5275.         end if;
  5276.         if INDENTION > 0 then
  5277.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(INDENTION));
  5278.         end if;
  5279.         TEXT_IO.PUT(TO_THIS,STYLE_ISSUE);
  5280.         if SUB_HEADING /= "" then
  5281.             TEXT_IO.SET_COL(TO_THIS,
  5282.                 TEXT_IO.POSITIVE_COUNT(SECOND_COLUMN_START));
  5283.             TEXT_IO.PUT(TO_THIS,SUB_HEADING);
  5284.         end if;
  5285.         TEXT_IO.SET_COL(TO_THIS,
  5286.                 TEXT_IO.POSITIVE_COUNT(DECIMAL_POINT_COLUMN - 4));
  5287.         TEXT_IO.PUT(TO_THIS,LEAD_IN);
  5288.         if UNITS /= PERCENT then
  5289.             -- if COUNT is too small then FLOAT_IO raises CONSTRAINT_ERROR
  5290.             if COUNT < 0.1 then
  5291.                 MY_FLOAT_IO.PUT(TO_THIS,0.0,FORE => 3, AFT => 1, EXP => 0);
  5292.                 TEXT_IO.SET_COL(TO_THIS,
  5293.                                 TEXT_IO.POSITIVE_COUNT(THIRD_COLUMN_START));
  5294.             else
  5295.                 MY_FLOAT_IO.PUT(TO_THIS,COUNT,FORE => 3, AFT => 1, EXP => 0);
  5296.                 TEXT_IO.SET_COL(TO_THIS,
  5297.                                 TEXT_IO.POSITIVE_COUNT(THIRD_COLUMN_START));
  5298.             end if;
  5299.         else
  5300.             -- if COUNT is too small then FLOAT_IO raises CONSTRAINT_ERROR
  5301.             if COUNT < 0.001 then
  5302.                 MY_FLOAT_IO.PUT(TO_THIS,0.0,FORE => 3, AFT => 1, EXP => 0);
  5303.             else
  5304.                 MY_FLOAT_IO.PUT(TO_THIS,(COUNT*100.0),
  5305.                                 FORE => 3,AFT => 1,EXP => 0);
  5306.             end if;
  5307.         end if;
  5308.         TEXT_IO.PUT_LINE(TO_THIS,UNITS);
  5309.     exception
  5310.         when others =>
  5311.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  5312.             TEXT_IO.PUT_LINE(" in PUT_REPORT_LINE(for FLOAT)");
  5313.             raise;
  5314.     end PUT_REPORT_LINE;
  5315.  
  5316.     procedure PUT_REPORT_LINE(INDENTION         : in NATURAL;
  5317.                               STYLE_ISSUE       : in STRING;
  5318.                               SUB_HEADING       : in STRING;
  5319.                               LOWER_BOUND       : in NATURAL;
  5320.                               UPPER_BOUND       : in NATURAL;
  5321.                               UNITS             : in STRING;
  5322.                               ASTERIK_NEEDED    : in BOOLEAN := FALSE;
  5323.                               EXCLAMATION_NEEDED: in BOOLEAN := FALSE) is
  5324.  
  5325.         COLUMN          : POSITIVE;
  5326.  
  5327.     begin
  5328.         if ASTERIK_NEEDED then
  5329.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5330.             TEXT_IO.PUT(TO_THIS,ASTERIK);
  5331.         elsif EXCLAMATION_NEEDED then
  5332.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5333.             TEXT_IO.PUT(TO_THIS,EXCLAMATION);
  5334.         end if;
  5335.         if INDENTION > 0 then
  5336.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(INDENTION));
  5337.         end if;
  5338.         TEXT_IO.PUT(TO_THIS,STYLE_ISSUE);
  5339.         if SUB_HEADING /= "" then
  5340.             TEXT_IO.SET_COL(TO_THIS,
  5341.                 TEXT_IO.POSITIVE_COUNT(SECOND_COLUMN_START));
  5342.             TEXT_IO.PUT(TO_THIS,SUB_HEADING);
  5343.         end if;
  5344.         if (LOWER_BOUND < 10) then
  5345.             COLUMN := DECIMAL_POINT_COLUMN - 1;
  5346.         elsif (LOWER_BOUND < 100)
  5347.             then COLUMN := DECIMAL_POINT_COLUMN - 2;
  5348.         elsif (LOWER_BOUND < 1000)
  5349.             then COLUMN := DECIMAL_POINT_COLUMN - 3;
  5350.         else COLUMN := DECIMAL_POINT_COLUMN - 4;
  5351.         end if;
  5352.         if (UPPER_BOUND < 10) then
  5353.             COLUMN := COLUMN - 1;
  5354.         elsif (UPPER_BOUND < 100)
  5355.             then COLUMN := COLUMN - 2;
  5356.         elsif (UPPER_BOUND < 1000)
  5357.             then COLUMN := COLUMN - 3;
  5358.         else COLUMN := COLUMN - 4;
  5359.         end if;
  5360.         COLUMN := COLUMN - 2;
  5361.         TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(COLUMN));
  5362.         NATURAL_IO.PUT(TO_THIS,LOWER_BOUND,0);
  5363.         TEXT_IO.PUT(TO_THIS,DOT_DOT);
  5364.         NATURAL_IO.PUT(TO_THIS,UPPER_BOUND,0);
  5365.         TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(THIRD_COLUMN_START));
  5366.         TEXT_IO.PUT_LINE(TO_THIS,UNITS);
  5367.     exception
  5368.         when others =>
  5369.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  5370.             TEXT_IO.PUT_LINE(" in PUT_REPORT_LINE(for RANGES)");
  5371.             raise;
  5372.     end PUT_REPORT_LINE;
  5373.  
  5374.     procedure PUT_REPORT_LINE(
  5375.                 KEYWORD_REPORT  : in STYLE_PARAMETERS.KEYWORD_USE_DESCRIPT;
  5376.                 KEYWORD_COUNT   : in NATURAL;
  5377.                 KEYWORD_USAGE   : in FLOAT;
  5378.                 KEYWORD_TYPE    : in TOKENIZER.TOKEN_TYPE) is
  5379.  
  5380.     use STYLE_PARAMETERS;
  5381.         package TOKEN_TYPE_IO is new
  5382.                 TEXT_IO.ENUMERATION_IO(TOKENIZER.TOKEN_TYPE);
  5383.         TOKEN_STRING    : STRING(1..20);
  5384.         UNDERSCORE_COLUMN : NATURAL := 1;
  5385.  
  5386.     begin
  5387.         if (KEYWORD_REPORT.USE_CLASS /= FREE_USE) and
  5388.            (KEYWORD_USAGE > KEYWORD_REPORT.USE_FREQ) then
  5389.             TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(ERROR_FLAG_COLUMN));
  5390.             TEXT_IO.PUT(TO_THIS,ASTERIK);
  5391.         end if;
  5392.         TEXT_IO.SET_COL(TO_THIS,TEXT_IO.POSITIVE_COUNT(FIRST_COLUMN_START));
  5393.         TOKEN_TYPE_IO.PUT(TOKEN_STRING,KEYWORD_TYPE);
  5394.         while TOKEN_STRING(UNDERSCORE_COLUMN) /= '_' loop
  5395.             UNDERSCORE_COLUMN := UNDERSCORE_COLUMN + 1;
  5396.         end loop;
  5397.         TEXT_IO.PUT(TO_THIS,TOKEN_STRING(1..UNDERSCORE_COLUMN - 1));
  5398.         TEXT_IO.SET_COL(TO_THIS,17);
  5399.         if KEYWORD_REPORT.USE_CLASS = NO_USE then
  5400.             TEXT_IO.PUT(TO_THIS," no");
  5401.         else
  5402.             TEXT_IO.PUT(TO_THIS,"yes");
  5403.         end if;
  5404.         TEXT_IO.SET_COL(TO_THIS,31);
  5405.         -- if number is too small then FLOAT_IO raises CONSTRAINT_ERROR
  5406.         if KEYWORD_REPORT.USE_FREQ < 0.001 then
  5407.             MY_FLOAT_IO.PUT(TO_THIS,0.0,FORE => 3, AFT => 1, EXP => 0);
  5408.         else
  5409.             MY_FLOAT_IO.PUT(TO_THIS,(KEYWORD_REPORT.USE_FREQ * 100.0),
  5410.                 FORE => 3, AFT => 1, EXP => 0);
  5411.         end if;
  5412.         TEXT_IO.PUT(TO_THIS,PERCENT);
  5413.  
  5414.         TEXT_IO.SET_COL(TO_THIS,47);
  5415.         NATURAL_IO.PUT(TO_THIS,KEYWORD_COUNT,3);
  5416.  
  5417.         TEXT_IO.SET_COL(TO_THIS,63);
  5418.  
  5419.         -- if number is too small then FLOAT_IO raises CONSTRAINT_ERROR
  5420.         if KEYWORD_USAGE < 0.001 then
  5421.             MY_FLOAT_IO.PUT(TO_THIS,0.0,FORE => 3, AFT => 1, EXP => 0);
  5422.         else
  5423.             MY_FLOAT_IO.PUT(TO_THIS,(KEYWORD_USAGE * 100.0),
  5424.                 FORE => 3, AFT => 1, EXP => 0);
  5425.         end if;
  5426.         TEXT_IO.PUT_LINE(TO_THIS,PERCENT);
  5427.     exception
  5428.         when others =>
  5429.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  5430.             TEXT_IO.PUT_LINE(" in PUT_REPORT_LINE(for KEYWORDS)");
  5431.             raise;
  5432.     end PUT_REPORT_LINE;
  5433.  
  5434.  
  5435.     procedure PRINT_LIST ( LIST : in STRING_LIST_TYPE ) is
  5436.     NODE : STRING_LIST_TYPE;
  5437.     begin
  5438.         NODE := LIST;
  5439.         while NODE /= null loop
  5440.            PUT_REPORT_LINE( SECOND_COLUMN_START, DYN.STR(NODE.NAME) );
  5441.            NODE := NODE.NEXT;
  5442.         end loop;
  5443.     end PRINT_LIST;
  5444.  
  5445.  
  5446.     begin
  5447.  
  5448.         PUT_REPORT_LINE(0,"STYLE Report");
  5449.         PUT_REPORT_LINE(0,DYN.STR(FILE_NAME));
  5450.         PUT_REPORT_LINE(0,"");
  5451.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5452.                              "Naming Conventions");
  5453.         PUT_REPORT_LINE(0,HEADER_LINE);
  5454.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5455.                 "Invalid Case for an Object Identifier","",' ',
  5456.                 FROM_THIS.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER,ERRORS,
  5457.                 FROM_THIS.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER /= 0);
  5458.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Invalid Case for a Keyword",
  5459.                 "",' ',FROM_THIS.INVALID_CASE_FOR_A_KEYWORD,ERRORS,
  5460.                 FROM_THIS.INVALID_CASE_FOR_A_KEYWORD /= 0);
  5461.         if FROM_THIS.ABBREVIATIONS then
  5462.             PUT_REPORT_LINE(FIRST_COLUMN_START,"Too many abbreviations",
  5463.                             TRUE,FALSE);
  5464.         end if;
  5465.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5466.                 "Name Segment Size (Separated",DESIRED,LESS_THAN,
  5467.                 FROM_THIS.NAME_SEGMENT_SIZE_DESIRED_MAXIMUM,CHARACTERS);
  5468.         PUT_REPORT_LINE(19,"by Underscores)",ACTUAL,' ',
  5469.                 FROM_THIS.NAME_SEGMENT_SIZE_ACTUAL,CHARACTERS,
  5470.                 FROM_THIS.NAME_SEGMENT_SIZE_ACTUAL >
  5471.                 FLOAT(FROM_THIS.NAME_SEGMENT_SIZE_DESIRED_MAXIMUM));
  5472.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Average Name Size",
  5473.                 DESIRED,GREATER_THAN,
  5474.                 FROM_THIS.AVERAGE_NAME_SIZE_DESIRED_MINIMUM,CHARACTERS);
  5475.         PUT_REPORT_LINE(0,"",ACTUAL,' ',FROM_THIS.AVERAGE_NAME_SIZE_ACTUAL,
  5476.                 CHARACTERS,FROM_THIS.AVERAGE_NAME_SIZE_ACTUAL <
  5477.                 FLOAT(FROM_THIS.AVERAGE_NAME_SIZE_DESIRED_MINIMUM));
  5478.  
  5479.         PUT_REPORT_LINE(0,HEADER_LINE);
  5480.         PUT_REPORT_LINE(0,"");
  5481.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Physical Layout");
  5482.         PUT_REPORT_LINE(0,HEADER_LINE);
  5483.  
  5484.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5485.                 "Occurrences of More Than One Statement/Line","",' ',
  5486.                 FROM_THIS.OCCURRENCES_OF_MORE_THAN_ONE_STATEMENT_PER_LINE,
  5487.                 ERRORS,
  5488.                 FROM_THIS.OCCURRENCES_OF_MORE_THAN_ONE_STATEMENT_PER_LINE > 0);
  5489.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Inconsistant Indentation","",' ',
  5490.                 FROM_THIS.INCONSISTANT_INDENTATION,ERRORS,
  5491.                 FROM_THIS.INCONSISTANT_INDENTATION > 0);
  5492.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5493.                 "Missing Blank Lines to Set Off a Block","",' ',
  5494.                 FROM_THIS.MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK,ERRORS,
  5495.                 FROM_THIS.MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK > 0);
  5496. -- Don't look for prologs!
  5497. --      PUT_REPORT_LINE(FIRST_COLUMN_START,
  5498. --              "Missing Prolog","",' ',FROM_THIS.MISSING_PROLOG,
  5499. --              ERRORS,FROM_THIS.MISSING_PROLOG > 0);
  5500.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Loops Without Names","",' ',
  5501.                 FROM_THIS.LOOPS_WITHOUT_NAMES,"",
  5502.                 FROM_THIS.LOOPS_WITHOUT_NAMES > 0);
  5503. -- Don't care about blank lines
  5504. --      PUT_REPORT_LINE(FIRST_COLUMN_START,"Percent of Blank Lines",
  5505. --              DESIRED,GREATER_THAN,
  5506. --              FROM_THIS.PERCENT_OF_BLANK_LINES_DESIRED_MINIMUM,PERCENT);
  5507. --      PUT_REPORT_LINE(0,"",ACTUAL,' ',FROM_THIS.PERCENT_OF_BLANK_LINES_ACTUAL,
  5508. --              PERCENT,FROM_THIS.PERCENT_OF_BLANK_LINES_ACTUAL <
  5509. --              FROM_THIS.PERCENT_OF_BLANK_LINES_DESIRED_MINIMUM);
  5510.  
  5511.         PUT_REPORT_LINE(0,HEADER_LINE);
  5512.         PUT_REPORT_LINE(0,"");
  5513.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5514.                 "Information Hiding, Abstraction, Data Use");
  5515.         PUT_REPORT_LINE(0,HEADER_LINE);
  5516.  
  5517.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5518.                 "Percent of Literals In Body ",DESIRED,LESS_THAN,
  5519.                 FROM_THIS.PERCENT_OF_LITERALS_IN_BODY_DESIRED_MAXIMUM,PERCENT);
  5520.         PUT_REPORT_LINE(0,"",ACTUAL,' ',
  5521.                 FROM_THIS.PERCENT_OF_LITERALS_IN_BODY_ACTUAL,PERCENT,
  5522.                 FROM_THIS.PERCENT_OF_LITERALS_IN_BODY_ACTUAL >
  5523.                 FROM_THIS.PERCENT_OF_LITERALS_IN_BODY_DESIRED_MAXIMUM);
  5524.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5525.                 "Percent of Universal Types",DESIRED,LESS_THAN,
  5526.                 FROM_THIS.PERCENT_OF_UNIVERSAL_TYPES_DESIRED_MAXIMUM,PERCENT);
  5527.         PUT_REPORT_LINE(0,"",ACTUAL,' ',
  5528.                 FROM_THIS.PERCENT_OF_UNIVERSAL_TYPES_ACTUAL,PERCENT,
  5529.                 FROM_THIS.PERCENT_OF_UNIVERSAL_TYPES_ACTUAL >
  5530.                 FROM_THIS.PERCENT_OF_UNIVERSAL_TYPES_DESIRED_MAXIMUM);
  5531.         if FROM_THIS.DATA_STRUCTURING_TYPES_NOT_USED /=
  5532.                 (DATA_STRUCTURE_TYPES'FIRST .. DATA_STRUCTURE_TYPES'LAST =>
  5533.                  FALSE) then
  5534.             PUT_REPORT_LINE(FIRST_COLUMN_START,
  5535.                 "Data Structuring Types NOT Used",FALSE,TRUE);
  5536.             for DATA_TYPES in DATA_STRUCTURE_TYPES loop
  5537.                 if FROM_THIS.DATA_STRUCTURING_TYPES_NOT_USED(DATA_TYPES) then
  5538.                     case DATA_TYPES is
  5539.                         when ARRAY_TYPES =>
  5540.                             PUT_REPORT_LINE(SECOND_COLUMN_START,"Array Types");
  5541.                         when ENUMERATION_TYPES =>
  5542.                             PUT_REPORT_LINE(SECOND_COLUMN_START,
  5543.                                 "Enumeration Types");
  5544.                         when RECORD_TYPES =>
  5545.                             PUT_REPORT_LINE(SECOND_COLUMN_START,"Record Types");
  5546.                     end case;
  5547.                 end if;
  5548.             end loop;
  5549.         end if;
  5550.         if not FROM_THIS.ATTRIBUTES_USED then
  5551.             PUT_REPORT_LINE(FIRST_COLUMN_START,"No Attributes are Used",
  5552.                 FALSE,TRUE);
  5553.         end if;
  5554.  
  5555.         ADA_SPECIFICS_USED :=      FROM_THIS.AND_THENS_USED and
  5556.             FROM_THIS.OR_ELSES_USED and FROM_THIS.EXITS_USED and
  5557.             FROM_THIS.XORS_USED     and FROM_THIS.ELSIFS_USED and
  5558.             FROM_THIS.EXCEPTIONS_USED and FROM_THIS.INS_USED  and
  5559.             FROM_THIS.OUTS_USED     and FROM_THIS.IN_OUTS_USED and
  5560.             FROM_THIS.PRIVATES_USED;
  5561.         if NOT ADA_SPECIFICS_USED then
  5562.             PUT_REPORT_LINE( FIRST_COLUMN_START,
  5563.                 "Ada-Specific Features NOT used", FALSE, TRUE);
  5564.             if not FROM_THIS.AND_THENS_USED then
  5565.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"AND THEN");
  5566.             end if;
  5567.             if not FROM_THIS.OR_ELSES_USED then
  5568.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"OR ELSE");
  5569.             end if;
  5570.             if not FROM_THIS.EXITS_USED then
  5571.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"EXITS");
  5572.             end if;
  5573.             if not FROM_THIS.XORS_USED then
  5574.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"XOR");
  5575.             end if;
  5576.             if not FROM_THIS.ELSIFS_USED then
  5577.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"ELSIF");
  5578.             end if;
  5579.             if not FROM_THIS.EXCEPTIONS_USED then
  5580.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"EXCEPTION");
  5581.             end if;
  5582.             if not FROM_THIS.INS_USED then
  5583.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"IN parameters");
  5584.             end if;
  5585.             if not FROM_THIS.OUTS_USED then
  5586.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"OUT parameters");
  5587.             end if;
  5588.             if not FROM_THIS.IN_OUTS_USED then
  5589.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"IN OUT parameters");
  5590.             end if;
  5591.             if not FROM_THIS.PRIVATES_USED then
  5592.                 PUT_REPORT_LINE(SECOND_COLUMN_START,"PRIVATEs");
  5593.             end if;
  5594.         end if;
  5595.  
  5596.  
  5597.         PUT_REPORT_LINE(0,HEADER_LINE);
  5598.         PUT_REPORT_LINE(0,"");
  5599.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Modularity");
  5600.         PUT_REPORT_LINE(0,HEADER_LINE);
  5601.  
  5602.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Average Number of Parameters",
  5603.                 "Range",FROM_THIS.AVERAGE_NUMBER_OF_PARAMETERS_DESIRED_MINIMUM,
  5604.                 FROM_THIS.AVERAGE_NUMBER_OF_PARAMETERS_DESIRED_MAXIMUM,
  5605.                 PARAMETERS);
  5606.         PUT_REPORT_LINE(FIRST_COLUMN_START + 2,
  5607.                 "Instances of parameters below minimum","",' ',
  5608.                 FROM_THIS.INSTANCES_OF_PARAMETERS_BELOW_MINIMUM,"",
  5609.                 FROM_THIS.INSTANCES_OF_PARAMETERS_BELOW_MINIMUM > 0);
  5610.         PUT_REPORT_LINE(FIRST_COLUMN_START + 2,
  5611.                 "Instances of parameters above maximum","",' ',
  5612.                 FROM_THIS.INSTANCES_OF_PARAMETERS_ABOVE_MAXIMUM,"",
  5613.                 FROM_THIS.INSTANCES_OF_PARAMETERS_ABOVE_MAXIMUM > 0);
  5614.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Average Subprogram Size","Range",
  5615.                 FROM_THIS.AVERAGE_SUBPROGRAM_SIZE_DESIRED_MINIMUM,
  5616.                 FROM_THIS.AVERAGE_SUBPROGRAM_SIZE_DESIRED_MAXIMUM,
  5617.                 STATEMENTS);
  5618.         PUT_REPORT_LINE(FIRST_COLUMN_START + 2,
  5619.                 "Instances of size below minimum","",' ',
  5620.                 FROM_THIS.INSTANCES_OF_SIZE_BELOW_MINIMUM,"",
  5621.                 FROM_THIS.INSTANCES_OF_SIZE_BELOW_MINIMUM > 0);
  5622.         PUT_REPORT_LINE(FIRST_COLUMN_START +2,
  5623.                 "Instances of size above maximum","",' ',
  5624.                 FROM_THIS.INSTANCES_OF_SIZE_ABOVE_MAXIMUM,"",
  5625.                 FROM_THIS.INSTANCES_OF_SIZE_ABOVE_MAXIMUM > 0);
  5626.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5627.                 "Loops with too many exit statements","",' ',
  5628.                 FROM_THIS.INSTANCES_OF_TOO_MANY_EXITS,INSTANCES,
  5629.                 FROM_THIS.INSTANCES_OF_TOO_MANY_EXITS > 0);
  5630.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Control Structure Nesting",MAXIMUM,
  5631.                 ' ',FROM_THIS.CONTROL_STRUCTURE_NESTING_DESIRED_MAXIMUM,"");
  5632.         PUT_REPORT_LINE(0,"",EXCEEDED,' ',
  5633.                 FROM_THIS.CONTROL_STRUCTURE_NESTING_EXCEEDING_MAXIMUM,
  5634.                 INSTANCES,
  5635.                 FROM_THIS.CONTROL_STRUCTURE_NESTING_EXCEEDING_MAXIMUM > 0);
  5636.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Package Nesting",MAXIMUM,' ',
  5637.                 FROM_THIS.PACKAGE_NESTING_DESIRED_MAXIMUM,"");
  5638.         PUT_REPORT_LINE(0,"",EXCEEDED,' ',
  5639.                 FROM_THIS.PACKAGE_NESTING_EXCEEDING_MAXIMUM,INSTANCES,
  5640.                 FROM_THIS.PACKAGE_NESTING_EXCEEDING_MAXIMUM > 0);
  5641.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Subprogram Nesting",MAXIMUM,' ',
  5642.                 FROM_THIS.SUBPROGRAM_NESTING_DESIRED_MAXIMUM,"");
  5643.         PUT_REPORT_LINE(0,"",EXCEEDED,' ',
  5644.                 FROM_THIS.SUBPROGRAM_NESTING_EXCEEDING_MAXIMUM,INSTANCES,
  5645.                 FROM_THIS.SUBPROGRAM_NESTING_EXCEEDING_MAXIMUM > 0);
  5646.  
  5647.         PUT_REPORT_LINE(0,HEADER_LINE);
  5648.         PUT_REPORT_LINE(0,"");
  5649.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Comment Usage");
  5650.         PUT_REPORT_LINE(0,HEADER_LINE);
  5651.  
  5652.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Number of Comments","",' ',
  5653.                 FROM_THIS.NUMBER_OF_COMMENTS,COMMENTS);
  5654.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Average Comment Size",
  5655.                 DESIRED,GREATER_THAN,
  5656.                 FROM_THIS.AVERAGE_COMMENT_SIZE_DESIRED_MINIMUM,CHARACTERS);
  5657.         PUT_REPORT_LINE(0,"",ACTUAL,' ',FROM_THIS.AVERAGE_COMMENT_SIZE_ACTUAL,
  5658.                 CHARACTERS,FROM_THIS.AVERAGE_COMMENT_SIZE_ACTUAL <
  5659.                 FLOAT(FROM_THIS.AVERAGE_COMMENT_SIZE_DESIRED_MINIMUM));
  5660.  
  5661.         PUT_REPORT_LINE(0,HEADER_LINE);
  5662.         PUT_REPORT_LINE(0,"");
  5663.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Transportability");
  5664.         PUT_REPORT_LINE(0,HEADER_LINE);
  5665.  
  5666.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5667.                 "Number of Lines Exceeding Line Length","",' ',
  5668.                 FROM_THIS.NUMBER_OF_LINES_EXCEEDING_LINE_LENGTH,"",
  5669.                 FROM_THIS.NUMBER_OF_LINES_EXCEEDING_LINE_LENGTH > 0);
  5670.         for I in CHARACTER'FIRST .. CHARACTER'LAST loop
  5671.             if FROM_THIS.GRAPHIC_CHARACTERS_USED(I) > 0 then
  5672.                 case I is
  5673.                     when ASCII.NUL => ASCII_IMAGE := "'NUL'";
  5674.                     when ASCII.SOH => ASCII_IMAGE := "'SOH'";
  5675.                     when ASCII.STX => ASCII_IMAGE := "'STX'";
  5676.                     when ASCII.ETX => ASCII_IMAGE := "'ETX'";
  5677.                     when ASCII.EOT => ASCII_IMAGE := "'EOT'";
  5678.                     when ASCII.ENQ => ASCII_IMAGE := "'ENQ'";
  5679.                     when ASCII.ACK => ASCII_IMAGE := "'ACK'";
  5680.                     when ASCII.BEL => ASCII_IMAGE := "'BEL'";
  5681.                     when ASCII.BS  => ASCII_IMAGE := "'BS '";
  5682.                     when ASCII.HT  => ASCII_IMAGE := "'HT '";
  5683.                     when ASCII.LF  => ASCII_IMAGE := "'LF '";
  5684.                     when ASCII.VT  => ASCII_IMAGE := "'VT '";
  5685.                     when ASCII.FF  => ASCII_IMAGE := "'FF '";
  5686.                     when ASCII.CR  => ASCII_IMAGE := "'CR '";
  5687.                     when ASCII.SO  => ASCII_IMAGE := "'SO '";
  5688.                     when ASCII.SI  => ASCII_IMAGE := "'SI '";
  5689.                     when ASCII.DLE => ASCII_IMAGE := "'DLE'";
  5690.                     when ASCII.DC1 => ASCII_IMAGE := "'DC1'";
  5691.                     when ASCII.DC2 => ASCII_IMAGE := "'DC2'";
  5692.                     when ASCII.DC3 => ASCII_IMAGE := "'DC3'";
  5693.                     when ASCII.DC4 => ASCII_IMAGE := "'DC4'";
  5694.                     when ASCII.NAK => ASCII_IMAGE := "'NAK'";
  5695.                     when ASCII.SYN => ASCII_IMAGE := "'SYN'";
  5696.                     when ASCII.ETB => ASCII_IMAGE := "'ETB'";
  5697.                     when ASCII.CAN => ASCII_IMAGE := "'CAN'";
  5698.                     when ASCII.EM  => ASCII_IMAGE := "'EM '";
  5699.                     when ASCII.SUB => ASCII_IMAGE := "'SUB'";
  5700.                     when ASCII.ESC => ASCII_IMAGE := "'ESC'";
  5701.                     when ASCII.FS  => ASCII_IMAGE := "'FS '";
  5702.                     when ASCII.GS  => ASCII_IMAGE := "'GS '";
  5703.                     when ASCII.RS  => ASCII_IMAGE := "'RS '";
  5704.                     when ASCII.US  => ASCII_IMAGE := "'US '";
  5705.                     when ASCII.DEL => ASCII_IMAGE := "'DEL'";
  5706.                     when others => ASCII_IMAGE := "' "& I & " '";
  5707.                 end case;
  5708.                 PUT_REPORT_LINE(FIRST_COLUMN_START,
  5709.                     "Graphic (Non-Basic) Chararacter Used",
  5710.                     ASCII_IMAGE,' ',
  5711.                     FROM_THIS.GRAPHIC_CHARACTERS_USED(I),"",TRUE);
  5712.             end if;
  5713.         end loop;
  5714. -- Needs to be fixed later
  5715. --      PUT_REPORT_LINE(FIRST_COLUMN_START,
  5716. --              "Graphic (Non-Basic) Characters Used","",' ',
  5717. --              FROM_THIS.GRAPHIC_CHARACTERS_USED,"");
  5718. -- Needs to be fixed later
  5719. --      PUT_REPORT_LINE(FIRST_COLUMN_START,
  5720. --              "Non-Graphic Characters Used","",' ',
  5721. --              FROM_THIS.NON_GRAPHIC_CHARACTERS_USED,"");
  5722.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Address Clauses","",' ',
  5723.                 FROM_THIS.ADDRESS_CLAUSES,"",
  5724.                 FROM_THIS.ADDRESS_CLAUSES > 0);
  5725.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Representation Specifications","",
  5726.                 ' ',FROM_THIS.REPRESENTATION_SPECIFICATIONS,"",
  5727.                 FROM_THIS.REPRESENTATION_SPECIFICATIONS > 0);
  5728.  
  5729.         PUT_REPORT_LINE(FIRST_COLUMN_START,"PRAGMA'S used:" );
  5730.         PRINT_LIST(FROM_THIS.PRAGMAS_USED);
  5731.  
  5732.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Non-Standard PRAGMA's Used");
  5733.         PRINT_LIST(FROM_THIS.NON_STANDARD_PRAGMAS_USED );
  5734.  
  5735.         PUT_REPORT_LINE(FIRST_COLUMN_START,"Packages/Procedures WITHed" );
  5736.         PRINT_LIST( FROM_THIS.PACKAGES_PROCEDURES_WITHED );
  5737.  
  5738.         PUT_REPORT_LINE(0,HEADER_LINE);
  5739.         PUT_REPORT_LINE(0,"");
  5740.         PUT_REPORT_LINE(FIRST_COLUMN_START,
  5741.                 "* => Style Flaw        ! => Note: Potential for improvement");
  5742.         PUT_REPORT_LINE(0,"");
  5743.  
  5744.         if STYLE_PARAMETERS.OUTPUT_KEYWORD_LIST /= STYLE_PARAMETERS.NONE then
  5745.             PUT_REPORT_LINE(0,"Keyword Usage");
  5746.             PUT_REPORT_LINE(0," Used Keyword    Allowed         " &
  5747.                     "Restriction     Occurrences     Percentage");
  5748.             PUT_REPORT_LINE(0,HEADER_LINE);
  5749.             -- Figure out how many total keywords were used so we can figure
  5750.             -- percentages
  5751.             for I in TOKENIZER.KEYWORDS loop
  5752.                 KEYWORD_COUNT := KEYWORD_COUNT + FROM_THIS.TOKEN_COUNT(I);
  5753.             end loop;
  5754.             for I in TOKENIZER.KEYWORDS loop
  5755.                 if KEYWORD_COUNT > 0 then
  5756.                     KEYWORD_PERCENTAGES(I) := FLOAT(FROM_THIS.TOKEN_COUNT(I)) /
  5757.                         FLOAT(KEYWORD_COUNT);
  5758.                 else
  5759.                     KEYWORD_PERCENTAGES(I) := 0.0;
  5760.                 end if;
  5761.                 case STYLE_PARAMETERS.OUTPUT_KEYWORD_LIST is
  5762.                     when STYLE_PARAMETERS.ALL_KEYS =>
  5763.                         PUT_REPORT_LINE(FROM_THIS.KEYWORD_USAGE(I),
  5764.                             FROM_THIS.TOKEN_COUNT(I),KEYWORD_PERCENTAGES(I),I);
  5765.                     when STYLE_PARAMETERS.USED =>
  5766.                         if FROM_THIS.TOKEN_COUNT(I) > 0 then
  5767.                             PUT_REPORT_LINE(FROM_THIS.KEYWORD_USAGE(I),
  5768.                                 FROM_THIS.TOKEN_COUNT(I),KEYWORD_PERCENTAGES(I),
  5769.                                 I);
  5770.                         end if;
  5771.                     when STYLE_PARAMETERS.NOT_USED =>
  5772.                         if FROM_THIS.TOKEN_COUNT(I) = 0 then
  5773.                             PUT_REPORT_LINE(FROM_THIS.KEYWORD_USAGE(I),
  5774.                                 FROM_THIS.TOKEN_COUNT(I),KEYWORD_PERCENTAGES(I),
  5775.                                 I);
  5776.                         end if;
  5777.                     when STYLE_PARAMETERS.ERRORS =>
  5778.                         if (FROM_THIS.KEYWORD_USAGE(I).USE_CLASS /= FREE_USE)
  5779.                            and (KEYWORD_PERCENTAGES(I) >
  5780.                                 FROM_THIS.KEYWORD_USAGE(I).USE_FREQ) then
  5781.                             PUT_REPORT_LINE(FROM_THIS.KEYWORD_USAGE(I),
  5782.                                 FROM_THIS.TOKEN_COUNT(I),KEYWORD_PERCENTAGES(I),
  5783.                                 I);
  5784.                         end if;
  5785.                     when STYLE_PARAMETERS.NONE => null;
  5786.                 end case;
  5787.             end loop;
  5788.             PUT_REPORT_LINE(0,HEADER_LINE);
  5789.         end if;
  5790.         exception
  5791.             when others =>
  5792.                 TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  5793.                 TEXT_IO.PUT_LINE(" in GENERATE_REPORT");
  5794.                 raise;
  5795.     end GENERATE_REPORT;
  5796.  
  5797.     procedure INSERT_INTO_LIST ( LIST : in out STRING_LIST_TYPE;
  5798.                                  ELEMENT : DYN.DYN_STRING ) is
  5799.     -- Insert the element name into the list.
  5800.     -- Algorithm:  search the list.  If the element is not there,
  5801.     -- insert it at the end.
  5802.     LOOKAHEAD : STRING_LIST_TYPE;
  5803.     NEW_NODE  : STRING_LIST_TYPE;
  5804.     begin
  5805.         if LIST = null then
  5806.            -- Empty list, insert at beginning
  5807.            NEW_NODE := new STRING_NODE;
  5808.            NEW_NODE.NAME := DYN.D_STRING( DYN.UPPER_CASE( ELEMENT ) );
  5809.            LIST := NEW_NODE;
  5810.            return;
  5811.         else
  5812.            LOOKAHEAD := LIST;
  5813.         end if;
  5814.  
  5815.         -- Now search the list
  5816.         while LOOKAHEAD.NEXT /= null and
  5817.               DYN.STR(LOOKAHEAD.NAME) /= DYN.UPPER_CASE( ELEMENT ) loop
  5818.                 LOOKAHEAD  := LOOKAHEAD.NEXT;
  5819.         end loop;
  5820.         if LOOKAHEAD.NEXT = null then
  5821.             NEW_NODE := new STRING_NODE;
  5822.             NEW_NODE.NAME := DYN.D_STRING( DYN.UPPER_CASE( ELEMENT ) );
  5823.             LOOKAHEAD.NEXT := NEW_NODE;
  5824.         end if;
  5825.         return;
  5826.  
  5827. end INSERT_INTO_LIST;
  5828.  
  5829.  
  5830. end REPORT_GENERATOR;
  5831. ::::::::::
  5832. style_checker.ada
  5833. ::::::::::
  5834.  
  5835. with TOKENIZER;
  5836. with STYLE_PARAMETERS;
  5837. with REPORT_GENERATOR;
  5838. with DYN;
  5839. with HELP;
  5840. with DICTIONARY_MANAGER;
  5841. with CURRENT_EXCEPTION;
  5842. with TEXT_IO;
  5843. with FILE_HANDLING;
  5844. with STACK_PACKAGE;
  5845. procedure STYLE_CHECKER is
  5846. --------------------------------------------------------------------------
  5847. -- Abstract   : This is the main procedure of the Style_Checker.  It
  5848. --              contains types and global variables used by all the
  5849. --              style checker routines.
  5850. --------------------------------------------------------------------------
  5851. use TOKENIZER;
  5852.  
  5853.     DEBUG : BOOLEAN := false;       -- If 'on', debug information is printed
  5854.     VERSION : constant STRING := 
  5855.       "Ada STYLE CHECKER, Version 1.0; December 3, 1985";
  5856.  
  5857.     type UNIVERSAL_DATA_TYPE is (MY_INTEGER,
  5858.                                  MY_SHORT_INTEGER,
  5859.                                  MY_LONG_INTEGER,
  5860.                                  MY_FLOAT,
  5861.                                  MY_SHORT_FLOAT,
  5862.                                  MY_LONG_FLOAT,
  5863.                                  MY_NATURAL,
  5864.                                  MY_POSITIVE);
  5865.  
  5866.  
  5867.     type STATUS_RECORD is record
  5868.         CURRENT_TOKEN : TOKENIZER.TOKEN;
  5869.         CURRENT_INDENT     : NATURAL := 0;
  5870.         CURRENT_TRAIL_COMMENT_INDENT : NATURAL := 0;
  5871.         CURRENT_STATEMENTS : NATURAL := 0;
  5872.         CURRENT_LINE       : NATURAL := 0;
  5873.         EXITS_IN_LOOPS     : NATURAL := 0;
  5874.         TOTAL_LINES        : NATURAL := 0;
  5875.         TOTAL_BLANK_LINES  : NATURAL := 0;
  5876.         IN_BODY : BOOLEAN := FALSE;   --  As opposed to being in declarations
  5877.         IN_GENERIC         :BOOLEAN  := FALSE;
  5878.         PACKAGE_NEST_LEVEL : TOKENIZER.LINE_INDEX_RANGE;
  5879.         CONTROL_NEST_LEVEL : TOKENIZER.LINE_INDEX_RANGE;
  5880.         PROCEDURE_NEST_LEVEL : TOKENIZER.LINE_INDEX_RANGE;
  5881.         BEGIN_INDENT : BOOLEAN := true;
  5882.         SUBPROGRAM_NESTING_INFORMATION :
  5883.             REPORT_GENERATOR.AVERAGE_KEEPING_RECORD;
  5884.         BLANK_LINES_INFORMATION :
  5885.             REPORT_GENERATOR.AVERAGE_KEEPING_RECORD;
  5886.         COMMENT_INFORMATION :
  5887.             REPORT_GENERATOR.AVERAGE_KEEPING_RECORD;
  5888.         LITERAL_INFORMATION :
  5889.             REPORT_GENERATOR.AVERAGE_KEEPING_RECORD;
  5890.         UNIVERSAL_INFORMATION :
  5891.             REPORT_GENERATOR.AVERAGE_KEEPING_RECORD;
  5892.         IDENTIFIERS_INFORMATION :
  5893.             REPORT_GENERATOR.AVERAGE_KEEPING_RECORD;
  5894.         -- case of names and reserve words
  5895.         CASE_OF_RESERVED_WORDS  : STYLE_PARAMETERS.RESERVE_WORD_CASES :=
  5896.             STYLE_PARAMETERS.CASE_OF_RESERVED_WORDS;
  5897.         CASE_OF_OBJECT_NAMES    : STYLE_PARAMETERS.OBJECT_NAME_CASES :=
  5898.             STYLE_PARAMETERS.CASE_OF_OBJECT_NAMES;
  5899.     end record;
  5900.  
  5901.     type USAGE_RECORD is record
  5902.         ATTRIBUTES                      : boolean := false;
  5903.         DATA_STR_ARRAY                  : boolean := false;
  5904.         DATA_STR_ENUMERATION            : boolean := false;
  5905.         DATA_STR_RECORD                 : boolean := false;
  5906.         REPRESENTATION_SPECIFICATIONS   : boolean := false;
  5907.         ADDRESS_CLAUSES                 : boolean := false;
  5908.     end record;
  5909.  
  5910. --  Variables
  5911.  
  5912.     STYLE_REPORT : REPORT_GENERATOR.REPORT_RECORD;
  5913.  
  5914. --  Miscellaneous mistake records
  5915.  
  5916.     ABBREVIATIONS : NATURAL := 0;
  5917.  
  5918.     CONTROL_STRUCTURES_WITHOUT_LEADING_WHITE_SPACE :
  5919.         NATURAL := 0;
  5920.  
  5921.     COULD_HAVE_USED_AN_ELSIF : NATURAL := 0;
  5922.  
  5923.     DEEPEST_IF_NESTING : NATURAL := 0;
  5924.  
  5925.     DEEPEST_PACKAGE_NESTING : NATURAL := 0;
  5926.  
  5927.     DEEPEST_PROCEDURE_NESTING : NATURAL := 0;
  5928.  
  5929.     INDENTATION_ERRORS : NATURAL := 0;
  5930.  
  5931.     LONG_LOOPS_WITHOUT_LOOP_NAMES : NATURAL := 0;
  5932.  
  5933.     MISSING_UNDERSCORES : NATURAL := 0;
  5934.  
  5935.     MORE_THAN_ONE_STATEMENT_PER_LINE : NATURAL := 0;
  5936.  
  5937.     OBJECT_NAME_CAPITALIZATION_MISTAKES :
  5938.         array(STYLE_PARAMETERS.OBJECT_NAME_CASES) of NATURAL :=
  5939.              (STYLE_PARAMETERS.OBJECT_NAME_CASES'FIRST ..
  5940.               STYLE_PARAMETERS.OBJECT_NAME_CASES'LAST => 0);
  5941.  
  5942.     RESERVE_WORD_CAPITALIZATION_MISTAKES :
  5943.         array(STYLE_PARAMETERS.RESERVE_WORD_CASES) of NATURAL :=
  5944.              (STYLE_PARAMETERS.RESERVE_WORD_CASES'FIRST ..
  5945.               STYLE_PARAMETERS.RESERVE_WORD_CASES'LAST => 0);
  5946.  
  5947. -- Stack
  5948.  
  5949.    MAX_NESTING : constant positive := TOKENIZER.LINE_INDEX_RANGE'LAST;
  5950.  
  5951.    type NEST_TYPE is     (HEADER, PACKAGE_NEST, SUBPROGRAM_NEST, CONTROL_NEST);
  5952.    subtype NESTING_LEVEL is natural range 0..MAX_NESTING;
  5953.    type NESTING_RECORD is
  5954.      record
  5955.        LEVEL : NESTING_LEVEL;
  5956.        INDENT : TOKENIZER.LINE_INDEX_RANGE;
  5957.        STATEMENTS      : natural := 0;
  5958.        EXITS           : natural := 0;
  5959.        IN_BODY         : BOOLEAN := FALSE;
  5960.        KIND_OF_NEST    : NEST_TYPE;
  5961.        START_TOKEN     : TOKENIZER.TOKEN;
  5962.        PARAMETERS      : natural := 0;
  5963.        -- IN_PARAMS       : natural := 0;
  5964.        -- OUT_PARAMS      : natural := 0;
  5965.        -- IN_OUT_PARAMS   : natural := 0;
  5966.      end record;
  5967.    STACK_LIMIT : positive := MAX_NESTING;
  5968.  
  5969.    package  NEST_STACK is new STACK_PACKAGE(
  5970.                     ELEMENTS => NESTING_RECORD,
  5971.                     SIZE     => STACK_LIMIT );
  5972.  
  5973.    -- The stack itself
  5974.    MISC_NEST_STACK : NEST_STACK.HELP_INFO_STACK;
  5975.  
  5976. --  Dictionary pointer
  5977.  
  5978.     STYLE_DICTIONARY : DICTIONARY_MANAGER.DICTIONARY_PTR;
  5979.  
  5980. --  Files
  5981.  
  5982.     FLAWS_FILE : TEXT_IO.FILE_TYPE;
  5983.     STYLE_FILE : TEXT_IO.FILE_TYPE;
  5984.     FILE_NAME  : DYN.DYN_STRING := DYN.D_STRING("   ");
  5985.  
  5986. --  General purpose current status global variable
  5987.  
  5988.     CURRENT_STATUS : STATUS_RECORD;
  5989.     CURRENT_USAGE  : USAGE_RECORD;
  5990.  
  5991. --  functions
  5992.  
  5993.     function CURRENT_TOKEN return TOKENIZER.TOKEN;
  5994.  
  5995.     function PREVIOUS_NON_TRIVIAL_TOKEN(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  5996.         return TOKENIZER.TOKEN;
  5997.  
  5998.     function NEXT_NON_TRIVIAL_TOKEN(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  5999.         return TOKENIZER.TOKEN;
  6000.  
  6001.     function GET_NEXT_TOKEN_AND_UPDATE_COUNT return TOKENIZER.TOKEN;
  6002.  
  6003.     function IS_STATEMENT(EXAMINED_TOKEN : in TOKENIZER.TOKEN) return boolean;
  6004.  
  6005.     procedure NEW_LINE_TOKEN_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN);
  6006.  
  6007.     function SEARCH_FORWARD ( START_TOKEN : TOKENIZER.TOKEN;
  6008.                           GOAL_TYPE   : TOKENIZER.TOKEN_TYPE )
  6009.                           return TOKENIZER.TOKEN;
  6010.  
  6011.  
  6012.     function SEARCH_FORWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  6013.                           GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  6014.                           GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE )
  6015.                                              return TOKENIZER.TOKEN;
  6016.  
  6017.  -- Moving this to ENTERING_BLOCK
  6018.  -- function SEARCH_FORWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  6019.  --                       GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  6020.  --                       GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE;
  6021.  --                       GOAL_TYPE3   : TOKENIZER.TOKEN_TYPE )
  6022.  --                                          return TOKENIZER.TOKEN;
  6023.  
  6024.     function SEARCH_BACKWARD ( START_TOKEN : TOKENIZER.TOKEN;
  6025.                           GOAL_TYPE   : TOKENIZER.TOKEN_TYPE )
  6026.                           return TOKENIZER.TOKEN;
  6027.  
  6028.  
  6029.     function SEARCH_BACKWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  6030.                           GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  6031.                           GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE )
  6032.                                              return TOKENIZER.TOKEN;
  6033.  
  6034.     procedure BEGIN_OF_LINE_INDENTATION( CURRENT_TOKEN : TOKENIZER.TOKEN);
  6035.  
  6036.     procedure LITERAL_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN);
  6037.  
  6038.     procedure COMMENT_TOKEN_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN);
  6039.  
  6040.     procedure RESERVE_WORD_ENCOUNTERED(RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN);
  6041.  
  6042.     procedure OBJECT_NAME_ENCOUNTERED(OBJECT_NAME_TOKEN : in TOKENIZER.TOKEN);
  6043.  
  6044.     procedure ENTERING_BLOCK_STRUCTURE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN);
  6045.  
  6046.     procedure ENTERING_SUB_BLOCK_STRUCTURE(FROM_THIS_TOKEN: in TOKENIZER.TOKEN);
  6047.  
  6048.     procedure EXITING_BLOCK_STRUCTURE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN);
  6049.  
  6050.     procedure TYPE_DECLARATION(FROM_THIS_TOKEN : in TOKENIZER.TOKEN);
  6051.  
  6052.     procedure CHECK_THE_STYLE;
  6053.  
  6054.     procedure CHECK_END_OF_BLOCKS;
  6055.  
  6056.     procedure CHECK_STATEMENTS_PER_LINE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN);
  6057.  
  6058.     function CURRENT_TOKEN return TOKENIZER.TOKEN is separate;
  6059.  
  6060.     function PREVIOUS_NON_TRIVIAL_TOKEN(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6061.         return TOKENIZER.TOKEN is separate;
  6062.  
  6063.     function NEXT_NON_TRIVIAL_TOKEN(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6064.         return TOKENIZER.TOKEN is separate;
  6065.  
  6066.     function GET_NEXT_TOKEN_AND_UPDATE_COUNT return TOKENIZER.TOKEN is separate;
  6067.  
  6068.  
  6069.     function IS_STATEMENT(EXAMINED_TOKEN : in TOKENIZER.TOKEN) return boolean
  6070.         is separate;
  6071.  
  6072.     function SEARCH_FORWARD ( START_TOKEN : TOKENIZER.TOKEN;
  6073.                           GOAL_TYPE   : TOKENIZER.TOKEN_TYPE )
  6074.                           return TOKENIZER.TOKEN is separate;
  6075.  
  6076.  
  6077.     function SEARCH_FORWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  6078.                           GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  6079.                           GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE )
  6080.                                              return TOKENIZER.TOKEN is separate;
  6081.  
  6082. --  function SEARCH_FORWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  6083. --                        GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  6084. --                        GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE;
  6085. --                        GOAL_TYPE3   : TOKENIZER.TOKEN_TYPE )
  6086. --                                           return TOKENIZER.TOKEN is separate;
  6087. --
  6088.  
  6089.     function SEARCH_BACKWARD ( START_TOKEN : TOKENIZER.TOKEN;
  6090.                           GOAL_TYPE   : TOKENIZER.TOKEN_TYPE )
  6091.                           return TOKENIZER.TOKEN is separate;
  6092.  
  6093.  
  6094.     function SEARCH_BACKWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  6095.                           GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  6096.                           GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE )
  6097.                                              return TOKENIZER.TOKEN is separate;
  6098.  
  6099.     procedure NEW_LINE_TOKEN_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6100.               is separate;
  6101.  
  6102.     procedure BEGIN_OF_LINE_INDENTATION( CURRENT_TOKEN : TOKENIZER.TOKEN)
  6103.               is separate;
  6104.  
  6105.     procedure LITERAL_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6106.               is separate;
  6107.  
  6108.     procedure COMMENT_TOKEN_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6109.               is separate;
  6110.  
  6111.     procedure RESERVE_WORD_ENCOUNTERED(RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN)
  6112.               is separate;
  6113.  
  6114.     procedure OBJECT_NAME_ENCOUNTERED(OBJECT_NAME_TOKEN : in TOKENIZER.TOKEN)
  6115.               is separate;
  6116.  
  6117.     procedure ENTERING_BLOCK_STRUCTURE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6118.               is separate;
  6119.  
  6120.     procedure ENTERING_SUB_BLOCK_STRUCTURE(FROM_THIS_TOKEN: in TOKENIZER.TOKEN)
  6121.               is separate;
  6122.  
  6123.     procedure EXITING_BLOCK_STRUCTURE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6124.               is separate;
  6125.  
  6126.     procedure TYPE_DECLARATION(FROM_THIS_TOKEN : in TOKENIZER.TOKEN) is
  6127.               separate;
  6128.  
  6129.     procedure CHECK_THE_STYLE is separate;
  6130.  
  6131.     procedure CHECK_END_OF_BLOCKS is separate;
  6132.  
  6133.     procedure CHECK_STATEMENTS_PER_LINE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  6134.  
  6135.               is separate;
  6136.  
  6137. begin -- Style_Checker
  6138.     TEXT_IO.PUT_LINE( VERSION ); TEXT_IO.NEW_LINE;
  6139.     
  6140.     TOKENIZER.BUILD_TOKENS;
  6141.     if DEBUG then
  6142.       TEXT_IO.PUT_LINE("Finished building tokens.");
  6143.     end if;
  6144.     FILE_HANDLING.OUTPUT_FILE_ID(FLAWS_FILE,STYLE_FILE);
  6145.     if DEBUG then
  6146.       TEXT_IO.PUT_LINE("Finished opening files.");
  6147.     end if;
  6148.     DICTIONARY_MANAGER.CREATE_DICTIONARY(
  6149.         DICTIONARY_KIND => DICTIONARY_MANAGER.MASTER,
  6150.         DICTIONARY_IN   => STYLE_DICTIONARY,
  6151.         FILENAME        => FILE_HANDLING.STYLE_DICTIONARY_NAME );
  6152.     if DEBUG then
  6153.       TEXT_IO.PUT_LINE("Finished starting null dictionary.");
  6154.     end if;
  6155.     CHECK_THE_STYLE;
  6156.     if DEBUG then
  6157.       TEXT_IO.PUT_LINE("Finished check-the-style.");
  6158.     end if;
  6159.     REPORT_GENERATOR.GENERATE_REPORT(STYLE_REPORT,STYLE_FILE,FILE_NAME);
  6160.  
  6161.     TEXT_IO.PUT_LINE( "The FLAWS file is in: " & TEXT_IO.NAME( FLAWS_FILE ) );
  6162.     TEXT_IO.CLOSE(FLAWS_FILE);
  6163.     TEXT_IO.PUT_LINE( "The STYLE file is in: " & TEXT_IO.NAME( STYLE_FILE ) );
  6164.     TEXT_IO.CLOSE(STYLE_FILE);
  6165.  
  6166.     exception
  6167.         when FILE_HANDLING.HELP_ASKED_FOR =>
  6168.              begin  -- exceptions can be raised here!
  6169.                 --  call help file FILE_HANDLING.HELP_FILE_NAME
  6170.                 HELP.HELP_SCREEN( HELP.HELP,      FILE_HANDLING.HELP_FILE_NAME);
  6171.              exception
  6172.                 when HELP.HELP_OPEN_ERROR =>
  6173.                         TEXT_IO.PUT_LINE("Cannot Open the HELP File!");
  6174.                 when HELP.HELP_FILE_ERROR =>
  6175.                         TEXT_IO.PUT_LINE("Cannot find the HELP File!");
  6176.                 when HELP.HELP_FORMAT_ERROR =>
  6177.                         TEXT_IO.PUT_LINE(
  6178.                            "The HELP file is in the wrong format!");
  6179.              end;
  6180.         when others =>
  6181.              TEXT_IO.PUT("In STYLE_CHECKER main body: exception --");
  6182.              TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  6183.              TEXT_IO.PUT_LINE("Attempting to generate a partial Style Report");
  6184.              REPORT_GENERATOR.GENERATE_REPORT(STYLE_REPORT,
  6185.                                               STYLE_FILE,FILE_NAME);
  6186.              TEXT_IO.CLOSE(FLAWS_FILE);
  6187.              TEXT_IO.CLOSE(STYLE_FILE);
  6188.              raise;
  6189. end STYLE_CHECKER;
  6190. -- pragma MAIN;
  6191. ::::::::::
  6192. begin_of_line_indent.ada
  6193. ::::::::::
  6194.  
  6195. separate( STYLE_CHECKER )
  6196.  
  6197.  
  6198. procedure BEGIN_OF_LINE_INDENTATION ( CURRENT_TOKEN : TOKENIZER.TOKEN) is
  6199. --
  6200. -- PARAMETERS:
  6201. -- This is passed a token which should be at the start of
  6202. -- a line.
  6203. -- ABSTRACT:  This checks the indentation of the token.
  6204. -- ALGORITHM
  6205. -- Cases:
  6206. --          -- Comments.  There are too many radically different commenting
  6207. --          styles.  Comments are ignored for indentation.  (Note trailing
  6208. --          comments.)
  6209. -- Outdent for:  << labels >>
  6210. -- Indent for:   Statements, and {
  6211. --          else
  6212. --          when
  6213. --          elsif
  6214. --          begin
  6215. --          record
  6216. --          declare
  6217. --          generic
  6218. --          limited
  6219. --          private
  6220. --          "<<"}  -- left label brackett;
  6221. --
  6222. -- Otherwise:  Consider as the continuation of a statement.  In this case,
  6223. --          indentation should be greater than the 'normal'.
  6224. --
  6225. -- Determining indentation level.
  6226. -- The 'entering-block-structure' and 'leaving ...' sets flags about current
  6227. -- indentation levels.
  6228. --  If this is the first element after a block enter,
  6229. --    a flag will be set to indicate further indnetation is necessary.
  6230. --    If a comment - this is allowed to stay at the same level of indentation,
  6231. --    or be indented.
  6232. --    The first line is checked to see indentation is more than the outer block
  6233. --    level.  This sets the indentation level for the block.  The flags are
  6234. --    reset.
  6235. --  If this is a further line in the block, the indentation should match
  6236. --    what was there before.
  6237. --
  6238.  
  6239. use TOKENIZER;
  6240.  
  6241.   LOOKAHEAD : TOKENIZER.TOKEN;
  6242.   LINE      : TOKENIZER.LINE_NUM_RANGE;
  6243.   COLUMN    : TOKENIZER.LINE_INDEX_RANGE;
  6244.   SOURCE_LINE : DYN.DYN_STRING;
  6245.  
  6246.   -- Error messages
  6247.   LABEL_NOT_OUTDENTED : constant string :=
  6248.         "This Label should be outdented further!";
  6249.   LOOP_NOT_OUTDENTED  : constant string :=
  6250.         "This Loop-name should be outdented further!";
  6251.   CONTINUATION_NOT_INDENTED : constant string :=
  6252.         "The statement-continuation in this line should be indented!";
  6253.   LINE_NOT_INDENTED :         constant string :=
  6254.         "This line is not indented Properly!";
  6255.   LINE_SHOULD_BE_INDENTED :   constant string :=
  6256.         "This line should be indented to column:  ";
  6257.   LINE_TOO_LITTLE_INDENTED :  constant string :=
  6258.         "This line is not indented enough!";
  6259.   BEGIN_NOT_INDENTED :        constant string :=
  6260. "Beginning of this block not indented properly. Line ignored for Indentation!";
  6261.  
  6262.   function OTHER_INDENT_CASES( A_TOKEN : in TOKENIZER.TOKEN ) return boolean is
  6263.  
  6264.   begin
  6265.     case TOKENIZER.TYPE_OF_TOKEN_IS( A_TOKEN ) is
  6266.       when TOKENIZER.ELSE_TOKEN => return true;
  6267.       when TOKENIZER.WHEN_TOKEN => return true;
  6268.       when TOKENIZER.BEGIN_TOKEN => return true;
  6269.       when TOKENIZER.ELSIF_TOKEN => return true;
  6270.       when TOKENIZER.DECLARE_TOKEN => return true;  -- Is this correct?
  6271.       when TOKENIZER.GENERIC_TOKEN => return true;
  6272.       when TOKENIZER.LIMITED_TOKEN => return true;
  6273.       when TOKENIZER.PRIVATE_TOKEN => return true;
  6274.  
  6275.       when others => return false;
  6276.     end case;
  6277.  
  6278.   end OTHER_INDENT_CASES;
  6279.  
  6280.   function IS_LOOP_NAME( NAME_TOKEN : TOKENIZER.TOKEN ) return boolean is
  6281.   -- checks to find "IDENTIFIER :" which is a loop name
  6282.      LOOKAHEAD : TOKENIZER.TOKEN;
  6283.      LOOK2     : TOKENIZER.TOKEN;
  6284.   begin
  6285.      LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( NAME_TOKEN );
  6286.      LOOK2     := NEXT_NON_TRIVIAL_TOKEN( LOOKAHEAD );
  6287.      return TOKENIZER.TYPE_OF_TOKEN_IS( NAME_TOKEN) = TOKENIZER.IDENTIFIER and
  6288.         TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) = TOKENIZER.COLON  and
  6289.        (TOKENIZER.TYPE_OF_TOKEN_IS( LOOK2 ) = TOKENIZER.FOR_TOKEN or
  6290.         TOKENIZER.TYPE_OF_TOKEN_IS( LOOK2 ) = TOKENIZER.WHILE_TOKEN or
  6291.         TOKENIZER.TYPE_OF_TOKEN_IS( LOOK2 ) = TOKENIZER.LOOP_TOKEN);
  6292.   exception
  6293.     when END_OF_TOKENS =>
  6294.         return false;           -- at least let this continue!
  6295.     when others =>
  6296.         raise;
  6297.   end IS_LOOP_NAME;
  6298.  
  6299.  
  6300.   function LOOP_CONTINUATION( LOOP_TOKEN : TOKENIZER.TOKEN ) return boolean is
  6301.   -- ABSTRACT : Determine whether this is the LOOP token of a WHILE. . .LOOP
  6302.   --            statement.
  6303.   -- PARAMETER: LOOP_TOKEN is a token which is matched against the LOOP
  6304.   --            part of the WHILE... LOOP template
  6305.         LOOKAHEAD      : TOKENIZER.TOKEN;
  6306.         LOOKAHEAD_TYPE : TOKENIZER.TOKEN_TYPE;
  6307.  
  6308.   begin
  6309.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOP_TOKEN)=TOKENIZER.LOOP_TOKEN then
  6310.              -- look for a "FOR" or "WHILE"
  6311.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN( LOOP_TOKEN );
  6312.              while not IS_STATEMENT(LOOKAHEAD) loop
  6313.                      LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN( LOOKAHEAD );
  6314.              end loop;
  6315.              LOOKAHEAD_TYPE := TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD );
  6316.              if (LOOKAHEAD_TYPE = TOKENIZER.WHILE_TOKEN or
  6317.                      LOOKAHEAD_TYPE = TOKENIZER.FOR_TOKEN) then
  6318.                  -- this is the continuation of a while...loop statement!
  6319.                  return TRUE;
  6320.              else
  6321.                  return FALSE;
  6322.              end if;
  6323.         else
  6324.              return FALSE;
  6325.         end if;
  6326.   end LOOP_CONTINUATION;
  6327.  
  6328.  
  6329. begin
  6330.  
  6331.   -- check whether this is declarations and if those are required to be indented
  6332.   if CURRENT_STATUS.IN_BODY or
  6333.      STYLE_PARAMETERS.IS_DECLARATION_INDENTATION_REQUIRED then
  6334.  
  6335.    -- Position of Token
  6336.    TOKENIZER.TOKEN_POSITION( CURRENT_TOKEN, LINE, COLUMN );
  6337.  
  6338.    -- Determine indentation case
  6339.    if TOKENIZER.TYPE_OF_TOKEN_IS( CURRENT_TOKEN ) = LEFT_LABEL_BRACKET then
  6340.       -- Label - outdent!?
  6341.       if COLUMN >= CURRENT_STATUS.CURRENT_INDENT then
  6342.         -- Error! should be outdented!
  6343.         if not CURRENT_STATUS.BEGIN_INDENT then
  6344.             REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6345.                                 CURRENT_TOKEN, LABEL_NOT_OUTDENTED,
  6346.                                 REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6347.             STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6348.              STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6349.         -- else
  6350.         --   Hard to check for label indentation at the beginning of a block
  6351.         end if;
  6352.       end if;
  6353.  
  6354.    elsif IS_LOOP_NAME( CURRENT_TOKEN ) then
  6355.         if COLUMN > CURRENT_STATUS.CURRENT_INDENT or else
  6356.           (COLUMN = CURRENT_STATUS.CURRENT_INDENT and
  6357.            not CURRENT_STATUS.BEGIN_INDENT) then
  6358.             REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6359.                                 CURRENT_TOKEN, LOOP_NOT_OUTDENTED,
  6360.                                 REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6361.             STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6362.              STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6363.         end if;
  6364.  
  6365.  
  6366.    elsif (IS_STATEMENT(CURRENT_TOKEN) and not LOOP_CONTINUATION(CURRENT_TOKEN))
  6367.          or OTHER_INDENT_CASES(CURRENT_TOKEN) then
  6368.          -- Normal Statements!
  6369.          if CURRENT_STATUS.BEGIN_INDENT then
  6370.             -- This case is the beginning of an indented block
  6371.             if COLUMN > CURRENT_STATUS.CURRENT_INDENT then
  6372.                -- update the indentation count (beginning of block)
  6373.                CURRENT_STATUS.BEGIN_INDENT := false;
  6374.                -- This line established the indentation for the block!
  6375.                CURRENT_STATUS.CURRENT_INDENT := COLUMN;
  6376.             else
  6377.               case TOKENIZER.TYPE_OF_TOKEN_IS( CURRENT_TOKEN ) is
  6378.                 when
  6379.                     TOKENIZER.ELSE_TOKEN |
  6380.                     TOKENIZER.ELSIF_TOKEN |
  6381.                     TOKENIZER.WHEN_TOKEN |
  6382.                     TOKENIZER.BEGIN_TOKEN |
  6383.                     TOKENIZER.PRIVATE_TOKEN |
  6384.                     TOKENIZER.LIMITED_TOKEN |
  6385.                     TOKENIZER.GENERIC_TOKEN |
  6386.                     TOKENIZER.END_TOKEN |
  6387.                     TOKENIZER.EXCEPTION_TOKEN =>
  6388.                                 -- actually these should be indented to the
  6389.                                 -- last level of indentation to be precise!
  6390.                      if COLUMN < CURRENT_STATUS.CURRENT_INDENT then
  6391.                         REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6392.                           CURRENT_TOKEN, BEGIN_NOT_INDENTED,
  6393.                           REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6394.                         STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6395.                           STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6396.                      end if;
  6397.                 when TOKENIZER.COMMENT =>
  6398.                      null;
  6399.                 when others =>
  6400.                   REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6401.                         CURRENT_TOKEN, BEGIN_NOT_INDENTED,
  6402.                         REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6403.                         STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6404.                             STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6405.               end case;
  6406.             end if;
  6407.  
  6408.          else
  6409.             -- Indentation normal
  6410.             if COLUMN > CURRENT_STATUS.CURRENT_INDENT then
  6411.                    REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, CURRENT_TOKEN,
  6412.                       LINE_SHOULD_BE_INDENTED &
  6413.                       INTEGER'IMAGE(CURRENT_STATUS.CURRENT_INDENT),
  6414.                       REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6415.                    STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6416.                       STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6417.             elsif COLUMN < CURRENT_STATUS.CURRENT_INDENT then
  6418.               case TOKENIZER.TYPE_OF_TOKEN_IS( CURRENT_TOKEN ) is
  6419.                 when TOKENIZER.ELSE_TOKEN |
  6420.                     TOKENIZER.ELSIF_TOKEN |
  6421.                     TOKENIZER.WHEN_TOKEN |
  6422.                     TOKENIZER.BEGIN_TOKEN |
  6423.                     TOKENIZER.PRIVATE_TOKEN |
  6424.                     TOKENIZER.LIMITED_TOKEN |
  6425.                     TOKENIZER.GENERIC_TOKEN |
  6426.                     TOKENIZER.END_TOKEN |
  6427.                     TOKENIZER.EXCEPTION_TOKEN =>
  6428.                                 -- actually these should be indented to the
  6429.                                 -- last level of indentation to be precise!
  6430.                                 null; -- these are o.k.
  6431.                 when TOKENIZER.IDENTIFIER =>
  6432.                   -- check for loop names!
  6433.                   LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( CURRENT_TOKEN );
  6434.                   if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD)/=TOKENIZER.COLON
  6435.                     then
  6436.                       -- Not a loop name and should be indented!
  6437.                       REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6438.                         CURRENT_TOKEN, LINE_TOO_LITTLE_INDENTED,
  6439.                         REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6440.                         STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6441.                             STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6442.                   end if;
  6443.                 when TOKENIZER.FUNCTION_TOKEN |
  6444.                      TOKENIZER.PROCEDURE_TOKEN |
  6445.                      TOKENIZER.PACKAGE_TOKEN =>
  6446.                     if CURRENT_STATUS.IN_GENERIC then
  6447.                         null; -- spec should be outdented to generic level
  6448.                     else
  6449.                         REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6450.                             CURRENT_TOKEN, LINE_TOO_LITTLE_INDENTED,
  6451.                             REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6452.                         STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6453.                             STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6454.                     end if;
  6455.                 when others =>
  6456.                   REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6457.                         CURRENT_TOKEN, LINE_TOO_LITTLE_INDENTED,
  6458.                         REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6459.                         STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6460.                             STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6461.               end case;
  6462.             end if;
  6463.          end if;
  6464.  
  6465.    elsif TOKENIZER.TYPE_OF_TOKEN_IS( CURRENT_TOKEN ) = COMMENT then
  6466.          -- COMMENTS are ignored for indentation
  6467.          null;
  6468.  
  6469.    else
  6470.       -- Statement continuation - should be indented more than norm.
  6471.       -- UNLESS! this is a blank line!
  6472.      if TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= TOKENIZER.END_OF_LINE and
  6473.         TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= TOKENIZER.END_OF_FILE then
  6474.       if COLUMN <= CURRENT_STATUS.CURRENT_INDENT then
  6475.          REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  6476.                      CURRENT_TOKEN, CONTINUATION_NOT_INDENTED,
  6477.                      REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  6478.         STYLE_REPORT.INCONSISTANT_INDENTATION:=
  6479.              STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  6480.       end if;
  6481.      end if;
  6482.    end if;
  6483.   end if; -- if in declaration and no indentation checking required!
  6484. exception
  6485.    when others =>
  6486.       TEXT_IO.NEW_LINE;
  6487.       TEXT_IO.PUT("Inside BEGIN_OF_LINE_INDENTATION -- exception: " );
  6488.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME  );
  6489.       TEXT_IO.PUT("While in line:");
  6490.       TOKENIZER.LINE_CONTAINING_TOKEN(CURRENT_TOKEN,SOURCE_LINE );
  6491.       TEXT_IO.PUT_LINE( DYN.STR( SOURCE_LINE ) );
  6492.  
  6493. end BEGIN_OF_LINE_INDENTATION;
  6494. ::::::::::
  6495. check_statements.ada
  6496. ::::::::::
  6497. separate( STYLE_CHECKER )
  6498.  
  6499. procedure CHECK_STATEMENTS_PER_LINE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN ) is
  6500. -- ABSTRACT: This procedure checks to see if there are multiple statements
  6501. -- in this line.
  6502. --
  6503. -- Parameter:  FROM_THIS_TOKEN is a token which should be the first token
  6504. --             on the line.
  6505. -- Algorithm:  Every time a statement is encountered, we increment the
  6506. --             Current_statements counter.  Past the first token, a
  6507. --             statement sets the multiple-statements-per-line flag
  6508. --             UNLESS it is the following cases.
  6509. --              for . . . loop (loop ok)
  6510. --              while. . .loop (loop ok)
  6511. --              when. . => statement (is o.k.)
  6512. --             Finally, if multiple statements encountered, PUT_FLAW.
  6513. --
  6514. --             It was decided that the following case WAS ILLEGAL!
  6515. --             This has been commented out!
  6516. --              with X; use X; (use allowed)
  6517.  
  6518.  
  6519.  
  6520.  
  6521. use TOKENIZER;
  6522. MULTI_STATEMENT_FLAG : boolean;
  6523. LOOKAHEAD            : TOKENIZER.TOKEN;
  6524. FIRST_TYPE           : TOKENIZER.TOKEN_TYPE;
  6525. LOOKAHEAD_TYPE       : TOKENIZER.TOKEN_TYPE;
  6526. STATEMENTS_ON_LINE   : natural := 0;
  6527. MULTI_STMN_MSG       : constant string :=
  6528.         "There are more than one statements on this line!";
  6529. begin
  6530.     if IS_STATEMENT( FROM_THIS_TOKEN ) then
  6531.        STATEMENTS_ON_LINE := 1;
  6532.     else
  6533.        STATEMENTS_ON_LINE := 0;
  6534.     end if;
  6535.     FIRST_TYPE := TOKENIZER.TYPE_OF_TOKEN_IS( FROM_THIS_TOKEN );
  6536.     LOOKAHEAD := TOKENIZER.NEXT_TOKEN( FROM_THIS_TOKEN );
  6537.     MULTI_STATEMENT_FLAG := false;
  6538.  
  6539.     while TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) /= TOKENIZER.END_OF_LINE and
  6540.           TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) /= TOKENIZER.END_OF_FILE loop
  6541.        if IS_STATEMENT( LOOKAHEAD ) then
  6542.           STATEMENTS_ON_LINE := STATEMENTS_ON_LINE + 1;
  6543.           case TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) is
  6544.              when TOKENIZER.LOOP_TOKEN =>
  6545.                 -- Good examples:
  6546.                 --   for ... loop
  6547.                 --   for ...
  6548.                 --       ... loop
  6549.                 -- Bad
  6550.                 -- x := (y+z)*
  6551.                 --    p;  loop
  6552.                 if STATEMENTS_ON_LINE > 2 then
  6553.                     MULTI_STATEMENT_FLAG := true;
  6554.                 elsif IS_STATEMENT (FROM_THIS_TOKEN) then
  6555.                    if (FIRST_TYPE /= TOKENIZER.WHILE_TOKEN and
  6556.                      FIRST_TYPE /= TOKENIZER.FOR_TOKEN) then
  6557.                       MULTI_STATEMENT_FLAG := true;
  6558.                    end if;
  6559.                 else
  6560.                    -- look for a "FOR" or "WHILE"
  6561.                    LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN( FROM_THIS_TOKEN );
  6562.                    while not IS_STATEMENT(LOOKAHEAD) loop
  6563.                      LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN( LOOKAHEAD );
  6564.                    end loop;
  6565.                    LOOKAHEAD_TYPE := TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD );
  6566.                    if (LOOKAHEAD_TYPE /= TOKENIZER.WHILE_TOKEN and
  6567.                      LOOKAHEAD_TYPE /= TOKENIZER.FOR_TOKEN) then
  6568.                       MULTI_STATEMENT_FLAG := true;
  6569.                    end if;
  6570.                 end if;
  6571.  
  6572.             when others =>
  6573.                 if FIRST_TYPE = TOKENIZER.WHEN_TOKEN and
  6574.                    STATEMENTS_ON_LINE <2 then
  6575.                    null; -- this is ok!
  6576.                 else
  6577.                 MULTI_STATEMENT_FLAG := true;
  6578.                 end if;
  6579.           end case;
  6580.        end if;
  6581.  
  6582.        LOOKAHEAD := TOKENIZER.NEXT_TOKEN( LOOKAHEAD );
  6583.     end loop;
  6584.  
  6585.     if MULTI_STATEMENT_FLAG then
  6586.        REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, FROM_THIS_TOKEN,
  6587.          MULTI_STMN_MSG, REPORT_GENERATOR.MORE_THAN_ONE_STATEMENT_ON_LINE);
  6588.        STYLE_REPORT.OCCURRENCES_OF_MORE_THAN_ONE_STATEMENT_PER_LINE :=
  6589.        STYLE_REPORT.OCCURRENCES_OF_MORE_THAN_ONE_STATEMENT_PER_LINE + 1;
  6590.  
  6591.     end if;
  6592.  
  6593.    null;
  6594.     exception
  6595.         when END_OF_TOKENS =>
  6596.          null;
  6597.          -- This should be o.k.  END-OF-TOKENS will be handled elsewhere!
  6598.          -- TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  6599.          -- TEXT_IO.PUT_LINE(" in CHECK_STATEMENTS_PER_LINE");
  6600.         when others =>
  6601.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  6602.             TEXT_IO.PUT_LINE(" in CHECK_STATEMENTS_PER_LINE");
  6603.             raise;
  6604. end CHECK_STATEMENTS_PER_LINE;
  6605. ::::::::::
  6606. check_end_of_blocks.ada
  6607. ::::::::::
  6608. separate (STYLE_CHECKER)
  6609.  
  6610. procedure CHECK_END_OF_BLOCKS is
  6611. -- ABSTRACT: This checks to see if there are any extraneous
  6612. --           nesting elements left on the stack at the end of input.
  6613. --           If so it put out an error in the flaws file.
  6614.  
  6615. OLD_NEST_REC : NESTING_RECORD;
  6616. UNMATCHED_NEST_MSG : constant string :=
  6617.   "There are not enough 'ends' to close all the blocks at the end of input!";
  6618.  
  6619. begin
  6620.     NEST_STACK.POP( OLD_NEST_REC, MISC_NEST_STACK );
  6621.     while OLD_NEST_REC.KIND_OF_NEST /= HEADER loop
  6622.        -- unmatched nesting elements!
  6623.         REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, OLD_NEST_REC.START_TOKEN,
  6624.                 UNMATCHED_NEST_MSG, REPORT_GENERATOR.UNMATCHED_NESTING);
  6625.         NEST_STACK.POP( OLD_NEST_REC, MISC_NEST_STACK );
  6626.     end loop;
  6627.     -- restore the header record, just to make sure?
  6628.     NEST_STACK.PUSH( OLD_NEST_REC, MISC_NEST_STACK );
  6629.  
  6630.  
  6631.     null;
  6632.  
  6633. exception
  6634.         when others =>
  6635.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  6636.             TEXT_IO.PUT_LINE(" in CHECK_END_OF_BLOCKS");
  6637.             raise;
  6638. end CHECK_END_OF_BLOCKS;
  6639. ::::::::::
  6640. check_the_style.ada
  6641. ::::::::::
  6642. separate (STYLE_CHECKER)
  6643.  
  6644. procedure CHECK_THE_STYLE is
  6645. --------------------------------------------------------------------------
  6646. -- Abstract   : This procedure contains the main loop for the Style_Checker
  6647. --------------------------------------------------------------------------
  6648. -- Algorithm  : General algorithm is :
  6649. --                 Perform necessary initialization of global variables
  6650. --                 Get first token
  6651. --                 Go through all tokens in order, calling routines
  6652. --                      to handle each particular type of token
  6653. --                 Final clean up and name length checking
  6654. --------------------------------------------------------------------------
  6655.     use TOKENIZER;
  6656.     SOURCE_LINE      : DYN.DYN_STRING;
  6657.     NEST_HEADER      : NESTING_RECORD;
  6658.     CURRENT_TOKEN : TOKENIZER.TOKEN;
  6659.     LOOK_AHEAD_TOKEN : TOKENIZER.TOKEN;
  6660.     CH               : CHARACTER;
  6661.  
  6662.     FINAL_MSG : constant STRING :=
  6663.      "Finish checking started in above statement.  Total statements:";
  6664.  
  6665.     procedure CHECK_OBJECT_NAMES_SIZE is separate;
  6666.  
  6667.     procedure CHECK_FOR_ATTRIBUTE( AT_THIS_TOKEN : in TOKENIZER.TOKEN )
  6668.         is separate;
  6669.  
  6670.     procedure CHECK_UNIVERSAL ( THIS_TOKEN : TOKENIZER.TOKEN)
  6671.         is separate;
  6672.  
  6673. begin
  6674.  
  6675.     if DEBUG then
  6676.       TEXT_IO.PUT_LINE("Start Check-the-style");
  6677.     end if;
  6678.     -- Initialize the Nesting Stack -- JRM 2-20-85
  6679.     NEST_HEADER.LEVEL := 0;
  6680.     NEST_HEADER.INDENT := 1;
  6681.     NEST_HEADER.STATEMENTS := 0;
  6682.     NEST_HEADER.KIND_OF_NEST := HEADER;
  6683.     NEST_HEADER.START_TOKEN := TOKENIZER.FIRST_TOKEN;
  6684.     NEST_STACK.PUSH( NEST_HEADER, MISC_NEST_STACK );
  6685.  
  6686.     STYLE_PARAMETERS.RESERVED_WORD_INFO(STYLE_REPORT.KEYWORD_USAGE);
  6687.  
  6688.     STYLE_PARAMETERS.AVERAGE_SUBPROGRAM_SIZE
  6689.         (STYLE_REPORT.AVERAGE_SUBPROGRAM_SIZE_DESIRED_MINIMUM,
  6690.         STYLE_REPORT.AVERAGE_SUBPROGRAM_SIZE_DESIRED_MAXIMUM);
  6691.     STYLE_PARAMETERS.SUBPROGRAM_PARAMETERS
  6692.         (STYLE_REPORT.AVERAGE_NUMBER_OF_PARAMETERS_DESIRED_MINIMUM,
  6693.         STYLE_REPORT.AVERAGE_NUMBER_OF_PARAMETERS_DESIRED_MAXIMUM);
  6694.     begin
  6695.         loop
  6696.             CURRENT_TOKEN := GET_NEXT_TOKEN_AND_UPDATE_COUNT;
  6697.             -- First statement on the line
  6698.             if IS_STATEMENT(CURRENT_TOKEN) and
  6699.                TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN)/=WHILE_TOKEN and
  6700.                -- FOR and WHILE statements are covered by LOOP!
  6701.                TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN)/=FOR_TOKEN then
  6702.                 CURRENT_STATUS.CURRENT_STATEMENTS :=
  6703.                     CURRENT_STATUS.CURRENT_STATEMENTS + 1;
  6704.                 -- TEXT_IO.NEW_LINE;
  6705.                 -- TOKENIZER.LINE_CONTAINING_TOKEN(CURRENT_TOKEN, SOURCE_LINE );
  6706.                 -- TEXT_IO.PUT("New Statement in line:");
  6707.                 -- TEXT_IO.PUT_LINE( DYN.STR( SOURCE_LINE ) );
  6708.                 -- Check declarations.
  6709.                 if not CURRENT_STATUS.IN_BODY then
  6710.                    -- Count declarations & universal types.
  6711.                    CHECK_UNIVERSAL( CURRENT_TOKEN );
  6712.                 end if;
  6713.             end if;
  6714.             begin
  6715.                 LOOK_AHEAD_TOKEN := TOKENIZER.PREVIOUS_TOKEN(CURRENT_TOKEN);
  6716.                 if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  6717.                     TOKENIZER.END_OF_LINE then
  6718.                     CURRENT_STATUS.TOTAL_LINES:=CURRENT_STATUS.TOTAL_LINES+1;
  6719.  
  6720.                     if                        TOKENIZER.END_OF_LINE /=
  6721.                     TOKENIZER.TYPE_OF_TOKEN_IS( CURRENT_TOKEN ) then
  6722.                       -- Check for indentation at beginning of a
  6723.                       -- NON-BLANK line!
  6724.                       BEGIN_OF_LINE_INDENTATION(CURRENT_TOKEN);
  6725.                       --
  6726.                       -- Check for multiple statements per line
  6727.                       CHECK_STATEMENTS_PER_LINE( CURRENT_TOKEN );
  6728.                     else
  6729.                       CURRENT_STATUS.TOTAL_BLANK_LINES :=
  6730.                         CURRENT_STATUS.TOTAL_BLANK_LINES + 1;
  6731.                     end if;
  6732.                     -- Does this work for floating divide?
  6733.                     STYLE_REPORT.PERCENT_OF_BLANK_LINES_ACTUAL :=
  6734.                 FLOAT(CURRENT_STATUS.TOTAL_BLANK_LINES)      /
  6735.                   FLOAT(CURRENT_STATUS.TOTAL_LINES);
  6736.  
  6737.                 end if;
  6738.                 exception
  6739.                     when TOKENIZER.END_OF_TOKENS =>
  6740.                         BEGIN_OF_LINE_INDENTATION(CURRENT_TOKEN);
  6741.                 --
  6742.                 -- Check for multiple statements per line
  6743.                 CHECK_STATEMENTS_PER_LINE( CURRENT_TOKEN );
  6744.                     when others => raise;
  6745.             end;
  6746.             case TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) is
  6747.                 when TOKENIZER.KEYWORDS =>
  6748.                     RESERVE_WORD_ENCOUNTERED(CURRENT_TOKEN);
  6749.                 when TOKENIZER.END_OF_LINE =>
  6750.                     NEW_LINE_TOKEN_ENCOUNTERED(CURRENT_TOKEN);
  6751.                 when TOKENIZER.END_OF_FILE =>
  6752.                     if DYN.STR(FILE_NAME) = "   " then
  6753.                         FILE_NAME := TOKENIZER.EXTERNAL_REPRESENTATION(
  6754.                                          CURRENT_TOKEN);
  6755.                     end if;
  6756.                 when TOKENIZER.IDENTIFIER =>
  6757.                     OBJECT_NAME_ENCOUNTERED(CURRENT_TOKEN);
  6758.                 when TOKENIZER.NUMERIC_LITERAL | TOKENIZER.STRING_LITERAL  |
  6759.                     TOKENIZER.CHARACTER_LITERAL =>
  6760.                     LITERAL_ENCOUNTERED(CURRENT_TOKEN);
  6761.                 when TOKENIZER.SEMICOLON => null;
  6762.                 when TOKENIZER.COMMENT =>
  6763.                     COMMENT_TOKEN_ENCOUNTERED(CURRENT_TOKEN);
  6764.                 when TOKENIZER.TICK    =>
  6765.                     CHECK_FOR_ATTRIBUTE(CURRENT_TOKEN);
  6766. --      CONCATENATION_OPERATOR,  RIGHT_PARENTHESIS, LEFT_PARENTHESIS,
  6767. --      MULTIPLICATION_OPERATOR, ADDITION_OPERATOR, COMMA, SUBTRACTION_OPERATOR,
  6768. --      PERIOD, DIVISION_OPERATOR, COLON, LESS_THAN_OPERATOR, EQUAL_OPERATOR,
  6769. --      GREATER_THAN_OPERATOR, VERTICAL_BAR, ARROW, DOUBLE_DOT,
  6770. --      EXPONENTIATE_OPERATOR, ASSIGNMENT_OPERATOR, INEQUAL_OPERATOR,
  6771. --      GREATER_THAN_OR_EQUAL_OPERATOR, LESS_THAN_OR_EQUAL_OPERATOR,
  6772. --      LEFT_LABEL_BRACKET, RIGHT_LABEL_BRACKET, BOX
  6773.                 when TOKENIZER.ANYTHING_ELSE =>
  6774.                     for I in 1..DYN.LENGTH(
  6775.                         TOKENIZER.EXTERNAL_REPRESENTATION(CURRENT_TOKEN)) loop
  6776.                         case STYLE_PARAMETERS.CHARACTER_SET is
  6777.                             -- letters and numbers will not be handled here
  6778.                             -- Also most "Special characters"
  6779.                             when STYLE_PARAMETERS.GRAPHIC =>
  6780.                                 CH := DYN.STR(TOKENIZER.
  6781.                                         EXTERNAL_REPRESENTATION(
  6782.                                         CURRENT_TOKEN))(I);
  6783.                                 if CH /= ASCII.HT and CH /= ASCII.VT and
  6784.                                    CH /= ASCII.LF and CH /= ASCII.FF then
  6785.                                     REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,
  6786.                                         CURRENT_TOKEN, "Illegal character "
  6787.                                         & "in this line",
  6788.                                        REPORT_GENERATOR.GRAPHIC_CHARACTER_USED);
  6789.                                     STYLE_REPORT.GRAPHIC_CHARACTERS_USED(CH) :=
  6790.                                         STYLE_REPORT.GRAPHIC_CHARACTERS_USED(CH)
  6791.                                         + 1;
  6792.                                 end if;
  6793.                             when STYLE_PARAMETERS.BASIC =>
  6794.                                 CH := DYN.STR(TOKENIZER.EXTERNAL_REPRESENTATION(
  6795.                                               CURRENT_TOKEN))(I);
  6796.                                 REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,
  6797.                                     CURRENT_TOKEN, "Illegal character "
  6798.                                     & "in this line",
  6799.                                     REPORT_GENERATOR.GRAPHIC_CHARACTER_USED);
  6800.                                 STYLE_REPORT.GRAPHIC_CHARACTERS_USED(CH) :=
  6801.                                   STYLE_REPORT.GRAPHIC_CHARACTERS_USED(CH) + 1;
  6802.                             when STYLE_PARAMETERS.EXTENDED => null;
  6803.                         end case;
  6804.                     end loop;
  6805.                 when others => null;
  6806.             end case;
  6807.         end loop;
  6808.     exception
  6809.         when TOKENIZER.END_OF_TOKENS => null;
  6810.         when others => 
  6811.             TEXT_IO.PUT_LINE(
  6812.                "Some unrecognized error in Check-the-style's main loop.");
  6813.             raise;
  6814.     end;
  6815.     -- check to see if there are no unmatched block on the nest stack
  6816.     CHECK_END_OF_BLOCKS;
  6817.  
  6818.     CHECK_OBJECT_NAMES_SIZE;
  6819.  
  6820.     if CURRENT_STATUS.IDENTIFIERS_INFORMATION.NUMBER_OF_ITEMS /= 0 then
  6821.         STYLE_REPORT.AVERAGE_NAME_SIZE_ACTUAL :=
  6822.             FLOAT(CURRENT_STATUS.IDENTIFIERS_INFORMATION.TOTAL_SIZE_OF_ITEMS) /
  6823.             FLOAT(CURRENT_STATUS.IDENTIFIERS_INFORMATION.NUMBER_OF_ITEMS);
  6824.     end if;
  6825.  
  6826.     STYLE_REPORT.NUMBER_OF_COMMENTS :=
  6827.             CURRENT_STATUS.COMMENT_INFORMATION.NUMBER_OF_ITEMS;
  6828.     if CURRENT_STATUS.COMMENT_INFORMATION.NUMBER_OF_ITEMS /= 0 then
  6829.         STYLE_REPORT.AVERAGE_COMMENT_SIZE_ACTUAL :=
  6830.             FLOAT(CURRENT_STATUS.COMMENT_INFORMATION.TOTAL_SIZE_OF_ITEMS) /
  6831.             FLOAT(CURRENT_STATUS.COMMENT_INFORMATION.NUMBER_OF_ITEMS);
  6832.     end if;
  6833.  
  6834.     if CURRENT_STATUS.LITERAL_INFORMATION.NUMBER_OF_ITEMS /= 0 then
  6835.         STYLE_REPORT.PERCENT_OF_LITERALS_IN_BODY_ACTUAL :=
  6836.             FLOAT(CURRENT_STATUS.LITERAL_INFORMATION.TOTAL_SIZE_OF_ITEMS) /
  6837.             FLOAT(CURRENT_STATUS.LITERAL_INFORMATION.NUMBER_OF_ITEMS);
  6838.     end if;
  6839.  
  6840.     if CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS /= 0 then
  6841.         STYLE_REPORT.PERCENT_OF_UNIVERSAL_TYPES_ACTUAL :=
  6842.             FLOAT(CURRENT_STATUS.UNIVERSAL_INFORMATION.TOTAL_SIZE_OF_ITEMS) /
  6843.             FLOAT(CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS);
  6844.     end if;
  6845.  
  6846.     -- Print a final message of statement count!
  6847.     NEST_STACK.POP ( NEST_HEADER, MISC_NEST_STACK );
  6848.     REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, NEST_HEADER.START_TOKEN,
  6849.       FINAL_MSG & INTEGER'IMAGE(NEST_HEADER.STATEMENTS)  );
  6850.  
  6851.     exception
  6852.         when TOKENIZER.END_OF_TOKENS => null;
  6853.         when others =>
  6854.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  6855.             TEXT_IO.PUT_LINE(" in CHECK_THE_STYLE");
  6856.             TEXT_IO.PUT_LINE("Trying to generate a Style Report anyway!");
  6857.             CHECK_OBJECT_NAMES_SIZE;
  6858.             raise;
  6859. end CHECK_THE_STYLE;
  6860. ::::::::::
  6861. check_for_attribute.ada
  6862. ::::::::::
  6863. separate( STYLE_CHECKER.CHECK_THE_STYLE )
  6864.  
  6865. procedure CHECK_FOR_ATTRIBUTE ( AT_THIS_TOKEN : in TOKENIZER.TOKEN ) is
  6866. -- ABSTRACT: Check whether this is an attribute and set the usage-flag.
  6867. ---------------------------------------------------------------------
  6868. -- PARAMETERS:  AT_THIS_TOKEN is a token pointing to  the TICK
  6869. --              which we are trying to recognise as an attribute.
  6870. ----------------------------------------------------------------------
  6871. -- ALGORITHM:   A tick can either be an attribute or the separator
  6872. --              before an aggregate.
  6873. ----------------------------------------------------------------------
  6874. LOOKAHEAD : TOKENIZER.TOKEN;
  6875.  
  6876. begin
  6877.     LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( AT_THIS_TOKEN );
  6878.     if TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) /= TOKENIZER.LEFT_PARENTHESIS
  6879.                 then
  6880.         CURRENT_USAGE.ATTRIBUTES := true;
  6881.         STYLE_REPORT.ATTRIBUTES_USED := true;
  6882.     end if;
  6883.     exception
  6884.         when others =>
  6885.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  6886.             TEXT_IO.PUT_LINE(" in CHECK_FOR_ATTRIBUTE.");
  6887.             raise;
  6888. end CHECK_FOR_ATTRIBUTE;
  6889. ::::::::::
  6890. check_object_names.ada
  6891. ::::::::::
  6892. with TOKEN_DEFINITION;
  6893. separate (STYLE_CHECKER.CHECK_THE_STYLE)
  6894.  
  6895. procedure CHECK_OBJECT_NAMES_SIZE is
  6896. --------------------------------------------------------------------------
  6897. -- Abstract   : This routine calculates the name size information
  6898. --              for the Style_Checker
  6899. --------------------------------------------------------------------------
  6900.  
  6901.  
  6902.     TREE_ROOT : TOKENIZER.IDENTIFIER_TREE := TOKENIZER.TREE_ROOT;
  6903.     TOTAL_VOWELS_IN_NAMES       : NATURAL := 0;
  6904.     TOTAL_NAME_SEGMENTS         : NATURAL := 0;
  6905.     TOTAL_CHARACTERS_IN_SEGMENTS: NATURAL := 0;
  6906.     SPELL_CHECK_WORD            : TOKEN_DEFINITION.TOKEN_TYPE;
  6907.     FOUND                       : BOOLEAN;
  6908.  
  6909.     procedure TREE_FOLLOWER(T : in out TOKENIZER.IDENTIFIER_TREE) is
  6910.  
  6911.     begin
  6912.         if T /= null then
  6913.             -- traverse left tree
  6914.             TREE_FOLLOWER(T.LEFT);
  6915.             -- Update name segment information
  6916.             if DYN.LENGTH(T.REFERENCES.STRG) > STYLE_PARAMETERS.SMALL_WORD_SIZE
  6917.                 then
  6918.                 SPELL_CHECK_WORD.LENGTH := 0;
  6919.                 for I in 1..DYN.LENGTH(T.REFERENCES.STRG) loop
  6920.                     if (DYN.STR(T.REFERENCES.STRG)(I) = '_') then
  6921.                         TOTAL_NAME_SEGMENTS := TOTAL_NAME_SEGMENTS + 1;
  6922.                         DICTIONARY_MANAGER.TOKEN_IS_FOUND(STYLE_DICTIONARY,
  6923.                                                           SPELL_CHECK_WORD,
  6924.                                                           FOUND);
  6925.                         if not FOUND then
  6926.                             -- Not handled now...
  6927.                             null;
  6928.                         end if;
  6929.                         SPELL_CHECK_WORD.LENGTH := 0;
  6930.                     else
  6931.                         if SPELL_CHECK_WORD.LENGTH <
  6932.                             TOKEN_DEFINITION.TOKEN_LENGTH then
  6933.                             SPELL_CHECK_WORD.LENGTH :=
  6934.                                 SPELL_CHECK_WORD.LENGTH + 1;
  6935.                             SPELL_CHECK_WORD.WORD(SPELL_CHECK_WORD.LENGTH) :=
  6936.                                 DYN.STR(T.REFERENCES.STRG)(I);
  6937.                         end if;
  6938.                         TOTAL_CHARACTERS_IN_SEGMENTS :=
  6939.                             TOTAL_CHARACTERS_IN_SEGMENTS + 1;
  6940.                     end if;
  6941.                 end loop;
  6942.                 TOTAL_NAME_SEGMENTS := TOTAL_NAME_SEGMENTS + 1;
  6943.                 DICTIONARY_MANAGER.TOKEN_IS_FOUND(STYLE_DICTIONARY,
  6944.                     SPELL_CHECK_WORD,FOUND);
  6945.                 if not FOUND then
  6946.                 -- Not handled now...
  6947.                     null;
  6948.                 end if;
  6949.             end if;
  6950.             -- Count characters and vowels
  6951.             for I in 1..DYN.LENGTH(T.REFERENCES.STRG) loop
  6952.                 case DYN.STR(T.REFERENCES.STRG)(I) is
  6953.                     when 'a' | 'e' | 'i' | 'o' | 'u' | 'y' |
  6954.                          'A' | 'E' | 'I' | 'O' | 'U' | 'Y' =>
  6955.                         TOTAL_VOWELS_IN_NAMES := TOTAL_VOWELS_IN_NAMES + 1;
  6956.                     when others => null;
  6957.                 end case;
  6958.             end loop;
  6959.             -- Update name length information
  6960.             CURRENT_STATUS.IDENTIFIERS_INFORMATION.NUMBER_OF_ITEMS :=
  6961.                 CURRENT_STATUS.IDENTIFIERS_INFORMATION.NUMBER_OF_ITEMS + 1;
  6962.             CURRENT_STATUS.IDENTIFIERS_INFORMATION.TOTAL_SIZE_OF_ITEMS :=
  6963.                 CURRENT_STATUS.IDENTIFIERS_INFORMATION.TOTAL_SIZE_OF_ITEMS +
  6964.                 DYN.LENGTH(T.REFERENCES.STRG);
  6965.             -- traverse right tree
  6966.             TREE_FOLLOWER(T.RIGHT);
  6967.         end if;
  6968.     exception
  6969.         when others =>
  6970.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  6971.             TEXT_IO.PUT_LINE(" in TREE_FOLLOWER");
  6972.             raise;
  6973.     end TREE_FOLLOWER;
  6974.  
  6975. begin
  6976.     TREE_FOLLOWER(TREE_ROOT);
  6977.     STYLE_REPORT.ABBREVIATIONS :=
  6978.        TOTAL_CHARACTERS_IN_SEGMENTS /= 0 and then
  6979.        (FLOAT(TOTAL_VOWELS_IN_NAMES) / FLOAT(TOTAL_CHARACTERS_IN_SEGMENTS)) <
  6980.        STYLE_PARAMETERS.VOWEL_FREQUENCY;
  6981.     if TOTAL_NAME_SEGMENTS > 0 then
  6982.         STYLE_REPORT.NAME_SEGMENT_SIZE_ACTUAL :=
  6983.             FLOAT(TOTAL_CHARACTERS_IN_SEGMENTS) / FLOAT(TOTAL_NAME_SEGMENTS);
  6984.     end if;
  6985.     exception
  6986.         when others =>
  6987.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  6988.             TEXT_IO.PUT_LINE(" in CHECK_OBJECT_NAMES_SIZE");
  6989.             raise;
  6990. end CHECK_OBJECT_NAMES_SIZE;
  6991. ::::::::::
  6992. check_universal.ada
  6993. ::::::::::
  6994. separate( STYLE_CHECKER.CHECK_THE_STYLE )
  6995.  
  6996. procedure CHECK_UNIVERSAL ( THIS_TOKEN : TOKENIZER.TOKEN ) is
  6997. -- ABSTRACT:  this procedure checks for the presence of a declaration
  6998. -- which is a universal type.
  6999. -- Parameters  THIS_ToKEN points to the token which is the
  7000. --      beginning of the declaration.
  7001.  
  7002.   use TOKENIZER;
  7003.  
  7004.   LOOKAHEAD : TOKENIZER.TOKEN;
  7005.   ID_COUNT  : POSITIVE;
  7006.  
  7007.   -- Until declarations are parsed better, these will not be used!
  7008.   MIS_PARSED_DECLARATION : exception;
  7009.   MIS_PARSED_MSG : constant string :=
  7010.  "Failed to parse declaration.  Either Ada is wrong or this program in error!";
  7011.  
  7012.   function IS_UNIVERSAL( TYPE_TOKEN : TOKENIZER.TOKEN ) return boolean is
  7013.     NAME : DYN.DYN_STRING;
  7014.   begin
  7015.     NAME      := TOKENIZER.EXTERNAL_REPRESENTATION( TYPE_TOKEN );
  7016.  
  7017.     return
  7018.         DYN.UPPER_CASE(NAME) = "INTEGER" or
  7019.         DYN.UPPER_CASE(NAME) = "SHORT_INTEGER" or
  7020.         DYN.UPPER_CASE(NAME) = "LONG_INTEGER"  or
  7021.         DYN.UPPER_CASE(NAME) = "FLOAT"         or
  7022.         DYN.UPPER_CASE(NAME) = "SHORT_FLOAT"   or
  7023.         DYN.UPPER_CASE(NAME) = "LONG_FLOAT"  or
  7024.         DYN.UPPER_CASE(NAME) = "NATURAL"       or
  7025.         DYN.UPPER_CASE(NAME) = "POSITIVE";
  7026. end IS_UNIVERSAL;
  7027.  
  7028. begin
  7029.     LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( THIS_TOKEN );
  7030.     case TOKENIZER.TYPE_OF_TOKEN_IS( THIS_TOKEN ) is
  7031.         when TOKENIZER.TYPE_TOKEN    =>
  7032.             CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS :=
  7033.                 CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS + 1;
  7034.  
  7035.         when TOKENIZER.SUBTYPE_TOKEN =>
  7036.             CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS :=
  7037.                 CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS + 1;
  7038.  
  7039.         when TOKENIZER.IDENTIFIER    =>
  7040.             -- Find out how many identifiers
  7041.             ID_COUNT := 1;
  7042.             LOOKAHEAD := SEARCH_FORWARD_FOR_ONE_OF(THIS_TOKEN,
  7043.                          TOKENIZER.COMMA,TOKENIZER.COLON);
  7044.             while TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD)=TOKENIZER.COMMA loop
  7045.                 ID_COUNT := ID_COUNT + 1;
  7046.                 LOOKAHEAD := SEARCH_FORWARD_FOR_ONE_OF(LOOKAHEAD,
  7047.                          TOKENIZER.COMMA,TOKENIZER.COLON);
  7048.             end loop;
  7049.  
  7050.             CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS :=
  7051.                CURRENT_STATUS.UNIVERSAL_INFORMATION.NUMBER_OF_ITEMS + ID_COUNT;
  7052.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) = TOKENIZER.COLON then
  7053.                 -- object declaration
  7054.                 LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( LOOKAHEAD );
  7055.                 -- look for exception or array
  7056.                 if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) =
  7057.                    TOKENIZER.EXCEPTION_TOKEN   or
  7058.                    TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) =
  7059.                    TOKENIZER.ARRAY_TOKEN then
  7060.                         -- these are O.K.!
  7061.                         null;
  7062.                 else
  7063.                   -- look for CONSTANT
  7064.                   if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) =
  7065.                    TOKENIZER.CONSTANT_TOKEN then
  7066.                         -- move to the identifier past CONSTANT!
  7067.                         LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( LOOKAHEAD );
  7068.                   end if;
  7069.                   if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) =
  7070.                    TOKENIZER.IDENTIFIER then
  7071.                     if IS_UNIVERSAL( LOOKAHEAD ) then
  7072.                        CURRENT_STATUS.UNIVERSAL_INFORMATION.
  7073.                                      TOTAL_SIZE_OF_ITEMS :=
  7074.                         CURRENT_STATUS.UNIVERSAL_INFORMATION.
  7075.                                      TOTAL_SIZE_OF_ITEMS + ID_COUNT;
  7076.                     end if;
  7077.                   else
  7078.                     null;
  7079.                     -- We need to parse declarations better here before
  7080.                     -- bad syntax can be noted!
  7081.                     -- raise MIS_PARSED_DECLARATION;
  7082.                   end if;
  7083.                 end if;
  7084.             end if;
  7085.         when others =>
  7086.             null;
  7087.     end case;
  7088.  
  7089.     exception
  7090.         when END_OF_TOKENS =>
  7091.             REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, THIS_TOKEN,
  7092.                                        MIS_PARSED_MSG );
  7093.         when MIS_PARSED_DECLARATION =>
  7094.             REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, THIS_TOKEN,
  7095.                                        MIS_PARSED_MSG );
  7096.             null;
  7097.         when others =>
  7098.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  7099.             TEXT_IO.PUT_LINE(" in CHECK_UNIVERSAL.");
  7100.             raise;
  7101. end CHECK_UNIVERSAL;
  7102. ::::::::::
  7103. comment_token.ada
  7104. ::::::::::
  7105. separate (STYLE_CHECKER)
  7106.  
  7107. procedure COMMENT_TOKEN_ENCOUNTERED ( FROM_THIS_TOKEN : in TOKENIZER.TOKEN ) is
  7108. -- ABSTRACT : This determines whether this is a 'trailing' comment,
  7109. --            If it is, its indentation is checked.
  7110. -- PARAMETERS : COMMENT_TOKEN is the token containing the comment to check.
  7111. -- ALGORITHM  : This is a trailing comment if:
  7112. --      The indentation level is
  7113. --      greater then current-indentation.
  7114. --      The trailing indentation level is set when:
  7115. --        The first trailing comment in a section is discovered (i.e. the
  7116. --        old trailing-indent is 0), or
  7117. --        Reset when a trailing comment has different indentation (this
  7118. --        offending comment is flagged if the style requires, or
  7119. --        Reset to 0 when a package, procedure, etc. is exited.
  7120.   use TOKENIZER;
  7121.  
  7122.   LOOKAROUND    : TOKENIZER.TOKEN;
  7123.   LINE          : TOKENIZER.LINE_NUM_RANGE;
  7124.   COLUMN        : TOKENIZER.LINE_INDEX_RANGE;
  7125.  
  7126.   BAD_TRAILING_MSG      : constant string :=
  7127.     "The trailing comment here is inconsistantly indented.";
  7128.  
  7129. begin
  7130.   -- Increment comment size counters
  7131.   CURRENT_STATUS.COMMENT_INFORMATION.NUMBER_OF_ITEMS :=
  7132.     CURRENT_STATUS.COMMENT_INFORMATION.NUMBER_OF_ITEMS + 1;
  7133.   CURRENT_STATUS.COMMENT_INFORMATION.TOTAL_SIZE_OF_ITEMS :=
  7134.     CURRENT_STATUS.COMMENT_INFORMATION.TOTAL_SIZE_OF_ITEMS +
  7135.     TOKENIZER.LENGTH_OF_COMMENT( FROM_THIS_TOKEN );
  7136.  
  7137.   -- Check Trailing indentation?
  7138.   if STYLE_PARAMETERS.IS_COMMENT_INDENTATION_REQUIRED then
  7139.     -- The style says we should indent check indentation on trailing comments!
  7140.     LOOKAROUND := TOKENIZER.PREVIOUS_TOKEN( FROM_THIS_TOKEN );
  7141.     TOKENIZER.TOKEN_POSITION( FROM_THIS_TOKEN, LINE, COLUMN );
  7142.     if COLUMN > CURRENT_STATUS.CURRENT_INDENT then
  7143.         -- this is a trailing comment!
  7144.         if CURRENT_STATUS.CURRENT_TRAIL_COMMENT_INDENT = 0 then
  7145.             -- a first trailing comment!
  7146.             CURRENT_STATUS.CURRENT_TRAIL_COMMENT_INDENT := COLUMN;
  7147.         else
  7148.             if CURRENT_STATUS.CURRENT_TRAIL_COMMENT_INDENT /= COLUMN then
  7149.                 -- Bad trailing comment!
  7150.                 -- Reset the trailing indentation counter.
  7151.                 CURRENT_STATUS.CURRENT_TRAIL_COMMENT_INDENT := COLUMN;
  7152.                 REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, FROM_THIS_TOKEN,
  7153.                         BAD_TRAILING_MSG,
  7154.                         REPORT_GENERATOR.INCONSISTANT_INDENTATION);
  7155.                 STYLE_REPORT.INCONSISTANT_INDENTATION :=
  7156.                         STYLE_REPORT.INCONSISTANT_INDENTATION + 1;
  7157.             end if;
  7158.         end if;
  7159.     end if;
  7160.   end if;
  7161.     exception
  7162.         when TOKENIZER.END_OF_TOKENS =>
  7163.             -- First on the input.  No handling required!
  7164.             null;
  7165.         when others =>
  7166.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  7167.             TEXT_IO.PUT_LINE(" in COMMENT_TOKEN_ENCOUNTERED");
  7168.             raise;
  7169. end COMMENT_TOKEN_ENCOUNTERED;
  7170. ::::::::::
  7171. current_token.ada
  7172. ::::::::::
  7173. separate (STYLE_CHECKER)
  7174.  
  7175. function CURRENT_TOKEN return TOKENIZER.TOKEN is
  7176. --------------------------------------------------------------------------
  7177. -- Abstract   : This function returns the token that is considered to be
  7178. --              the current token for the Style_Checker.  The current
  7179. --              token is the last one "counted" by
  7180. --              GET_NEXT_TOKEN_AND_UPDATE_COUNT.
  7181. --------------------------------------------------------------------------
  7182.  
  7183. begin
  7184.     return CURRENT_STATUS.CURRENT_TOKEN;
  7185.     exception
  7186.         when others =>
  7187.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  7188.             TEXT_IO.PUT_LINE(" in CURRENT_TOKEN");
  7189.             raise;
  7190. end CURRENT_TOKEN;
  7191. ::::::::::
  7192. entering_block.ada
  7193. ::::::::::
  7194.  
  7195. separate( STYLE_CHECKER )
  7196.  
  7197. procedure ENTERING_BLOCK_STRUCTURE( FROM_THIS_TOKEN : in TOKENIZER.TOKEN ) is
  7198. -- ABSTRACT: This performs the operations necessary for entering a
  7199. --           block structure.  This initializes a record for the
  7200. --           nesting stack, prepares for indentation.  For Procedures,
  7201. --           and functions, it counts parameters.
  7202. --
  7203. -- PARAMETER: This is a token which is the beginning of the block.
  7204. -- ALGORITHM:
  7205. --   Check to make sure its the beginning of a block really.
  7206. --   Increment previous nesting counter (Partial count of statements!)
  7207. --   Prepare new nesting record.
  7208. --   if FROM_THIS_TOKEN = procedure | function then
  7209. --      Count parameters
  7210. --      Check parameter limits
  7211. --   end if;
  7212. --   Push nesting record.
  7213. --   Check indentation flag, and increment proper nesting counter;
  7214. --      Nesting is checked for:
  7215. --      Packages,
  7216. --      Functions, procedures, and tasks
  7217. --      Control Structures
  7218. -- Begin
  7219. -- Case
  7220. -- Declare (special handling, this prefaces a 'begin'
  7221. -- Do
  7222. -- Exception (block)
  7223. -- For
  7224. -- Function
  7225. -- Loop
  7226. -- Package
  7227. -- Procedure
  7228. -- Record
  7229. -- Select
  7230. -- Task
  7231. -- Then
  7232. use TOKENIZER;
  7233.  
  7234. NEW_NEST_REC : NESTING_RECORD;
  7235. OLD_NEST_REC : NESTING_RECORD;
  7236. SEARCH_TOKEN : TOKENIZER.TOKEN;
  7237. PARAM_COUNT  : natural;
  7238. BAD_BLOCK_START : exception;
  7239. SOURCE_LINE     : DYN.DYN_STRING;
  7240. SUBPROGRAM_NEST_EXCEEDED : constant string :=
  7241.     "This subprogram is nested too deeply!";
  7242. PACKAGE_NEST_EXCEEDED    : constant string :=
  7243.     "This package is nested too deeply!";
  7244. CONTROL_NEST_EXCEEDED    : constant string :=
  7245.     "This control structure is nested too deeply!";
  7246. OVERFLOW_MSG             : constant string :=
  7247.  "This is nested so deep the stack overflowed! Further results are uncertain!";
  7248. UNDERFLOW_MSG            : constant string :=
  7249.  "The nesting stack has underflowed unexpectedly.  Please check Ada syntax.";
  7250.  
  7251. function SEARCH_FORWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  7252.                           GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  7253.                           GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE;
  7254.                           GOAL_TYPE3   : TOKENIZER.TOKEN_TYPE )
  7255.                                              return TOKENIZER.TOKEN is
  7256. use TOKENIZER;
  7257. -- This searches FORWARD until it finds one of the token types
  7258. -- If the end of the list is found, the END_OF_FILE token is
  7259. -- returned as a 'failed' signal.
  7260.   CURRENT_TOKEN : TOKENIZER.TOKEN;
  7261.   SOURCE_LINE   : DYN.DYN_STRING;
  7262.  
  7263. begin
  7264.    CURRENT_TOKEN := NEXT_NON_TRIVIAL_TOKEN( START_TOKEN );
  7265.    while (TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE1) and
  7266.          (TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE2) and
  7267.          (TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE3) loop
  7268.      if TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) = END_OF_FILE then
  7269.         exit;  -- just return this token as a 'failed' signal.
  7270.      end if;
  7271.      CURRENT_TOKEN := NEXT_NON_TRIVIAL_TOKEN( CURRENT_TOKEN );
  7272.    end loop;
  7273.    return CURRENT_TOKEN;
  7274. exception
  7275.    when others =>
  7276.       TEXT_IO.NEW_LINE;
  7277.       TEXT_IO.PUT("Inside SEARCH_FORWARD -- exception:" );
  7278.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  7279.       TEXT_IO.PUT_LINE("While in line:");
  7280.       TOKENIZER.LINE_CONTAINING_TOKEN( START_TOKEN, SOURCE_LINE );
  7281.       TEXT_IO.PUT( DYN.STR( SOURCE_LINE ) );
  7282. end SEARCH_FORWARD_FOR_ONE_OF;
  7283.  
  7284.  
  7285.  
  7286.  
  7287.  
  7288.  
  7289. procedure HANDLE_PARAMETER_LIST( START : in TOKENIZER.TOKEN;
  7290.                                  PARAMETERS : out natural) is
  7291. -- ABSTRACT: This locates a parameter (declaration) list.  It
  7292. --           counts the parameters on the list.  This currently
  7293. --           only handles function and procedures.  (Entry and
  7294. --           accept are other possibilities.)
  7295. --           NOTE - It seems more obvious to do this as a function,
  7296. --           however there may later be other things to do to parameter
  7297. --           lists.
  7298. -- PARAMETERS: START is a token which is the start of the statement
  7299. --             (function or PROCEDURE).
  7300. --             PARAMETERS is returned as the number of parameters on the list.
  7301. -- ALGORITHM
  7302. --  If there is a parameter list, it starts with a "(" two tokens
  7303. --  past the START.  Then each individual parameter is separated by a
  7304. --  ";" with multiple names separated by ",".
  7305. -- So the number of parameters is the number of ";" and "," before a ")".
  7306.  
  7307. LOOKAHEAD : TOKENIZER.TOKEN;
  7308. COUNT     : natural;
  7309. SMALL_LIMIT : natural;
  7310. LARGE_LIMIT : natural;
  7311.  
  7312. BAD_FORMAL_PART : exception;
  7313. BAD_FORMAL_MSG : constant string :=
  7314.                          "The formal part is not recognized properly?";
  7315. TOO_FEW_PARAMS : constant string :=
  7316.     "The number of parameters is BELOW the set limit!";
  7317. TOO_MANY_PARAMS : constant string :=
  7318.     "The number of parameters is ABOVE the set limit!";
  7319.  
  7320. begin
  7321.  
  7322.    -- Make sure this is the proper kind of statement!
  7323.    case TOKENIZER.TYPE_OF_TOKEN_IS( START ) is
  7324.      when TOKENIZER.PROCEDURE_TOKEN | TOKENIZER.FUNCTION_TOKEN =>
  7325.        -- Determine whether there is a "format_part".
  7326.        LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( START );
  7327.        LOOKAHEAD := NEXT_NON_TRIVIAL_TOKEN( LOOKAHEAD );
  7328.        if TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) = TOKENIZER.LEFT_PARENTHESIS
  7329.         then
  7330.          -- Number of parameters is number of ";" or ","
  7331.          -- between "(" and ")" plus one.
  7332.          COUNT := 1;
  7333.          LOOKAHEAD := SEARCH_FORWARD_FOR_ONE_OF( LOOKAHEAD,
  7334.                       TOKENIZER.RIGHT_PARENTHESIS,TOKENIZER.SEMICOLON,
  7335.                       TOKENIZER.COMMA);
  7336.          while TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) = TOKENIZER.SEMICOLON or
  7337.                TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) = TOKENIZER.COMMA loop
  7338.             COUNT := COUNT + 1;
  7339.             LOOKAHEAD := SEARCH_FORWARD_FOR_ONE_OF( LOOKAHEAD,
  7340.                          TOKENIZER.RIGHT_PARENTHESIS,TOKENIZER.SEMICOLON,
  7341.                          TOKENIZER.COMMA );
  7342.             if TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) = TOKENIZER.END_OF_FILE
  7343.               then
  7344.                 -- cannot recognize the formal part properly.
  7345.                 raise BAD_FORMAL_PART;
  7346.             end if;
  7347.          end loop;
  7348.        else
  7349.          COUNT := 0;
  7350.        end if;
  7351.        -- Check for the parameter range:
  7352.        STYLE_PARAMETERS.SUBPROGRAM_PARAMETERS( SMALL_LIMIT, LARGE_LIMIT);
  7353.        if COUNT < SMALL_LIMIT then
  7354.            REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START, TOO_FEW_PARAMS,
  7355.            REPORT_GENERATOR.TOO_FEW_PARAMETERS);
  7356.            STYLE_REPORT.INSTANCES_OF_PARAMETERS_BELOW_MINIMUM :=
  7357.              STYLE_REPORT.INSTANCES_OF_PARAMETERS_BELOW_MINIMUM + 1;
  7358.        end if;
  7359.        if COUNT > LARGE_LIMIT then
  7360.            REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START, TOO_MANY_PARAMS,
  7361.            REPORT_GENERATOR.TOO_MANY_PARAMETERS);
  7362.            STYLE_REPORT.INSTANCES_OF_PARAMETERS_ABOVE_MAXIMUM :=
  7363.              STYLE_REPORT.INSTANCES_OF_PARAMETERS_ABOVE_MAXIMUM + 1;
  7364.        end if;
  7365.  
  7366.      when others =>
  7367.  
  7368.  
  7369.        COUNT := 0;
  7370.    end case;
  7371.  
  7372.    PARAMETERS := COUNT;
  7373.    return;
  7374.  
  7375. exception
  7376.    when BAD_FORMAL_PART =>
  7377.       TEXT_IO.NEW_LINE;
  7378.       TEXT_IO.PUT(BAD_FORMAL_MSG);
  7379.    when others =>
  7380.       TEXT_IO.NEW_LINE;
  7381.       TEXT_IO.PUT("Inside HANDLE_PARAMETER_LIST -- exception:" );
  7382.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  7383.  
  7384. end HANDLE_PARAMETER_LIST;
  7385.  
  7386. begin
  7387.    -- All the checking should have been done before this!
  7388.    -- We should only be here if we're entering an actual block
  7389.  
  7390.    -- Handle nesting records
  7391.    NEST_STACK.POP( OLD_NEST_REC, MISC_NEST_STACK );
  7392.    -- add on statements-to-date
  7393.    OLD_NEST_REC.STATEMENTS := OLD_NEST_REC.STATEMENTS +
  7394.                               CURRENT_STATUS.CURRENT_STATEMENTS;
  7395.    CURRENT_STATUS.CURRENT_STATEMENTS := 0;
  7396.    NEST_STACK.PUSH( OLD_NEST_REC, MISC_NEST_STACK );
  7397.    NEW_NEST_REC.INDENT := CURRENT_STATUS.CURRENT_INDENT;
  7398.    NEW_NEST_REC.STATEMENTS := 0;
  7399.    NEW_NEST_REC.START_TOKEN := FROM_THIS_TOKEN;
  7400.    NEW_NEST_REC.IN_BODY := CURRENT_STATUS.IN_BODY;
  7401.  
  7402.    CURRENT_STATUS.CURRENT_TRAIL_COMMENT_INDENT := 0;
  7403.  
  7404.    -- Determine kind of structure
  7405.    --  Possibilities are:
  7406.  
  7407.    case TOKENIZER.TYPE_OF_TOKEN_IS( FROM_THIS_TOKEN ) is
  7408.    -- Control blocks
  7409.      when TOKENIZER.BEGIN_TOKEN  =>
  7410. -------------------------------------------------------
  7411.          -- Check to see if preceeded by 'DECLARE'
  7412. -------------------------------------------------------
  7413.          CURRENT_STATUS.CONTROL_NEST_LEVEL :=
  7414.                       CURRENT_STATUS.CONTROL_NEST_LEVEL + 1;
  7415.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.CONTROL_NEST_LEVEL;
  7416.          NEW_NEST_REC.KIND_OF_NEST := CONTROL_NEST;
  7417.          NEW_NEST_REC.PARAMETERS   := 0;
  7418.          NEW_NEST_REC.START_TOKEN  := FROM_THIS_TOKEN;
  7419.  
  7420.      when TOKENIZER.CASE_TOKEN |
  7421.       TOKENIZER.FOR_TOKEN |
  7422.       TOKENIZER.DECLARE_TOKEN |
  7423.       TOKENIZER.RECORD_TOKEN |
  7424.       TOKENIZER.SELECT_TOKEN =>
  7425.          CURRENT_STATUS.CONTROL_NEST_LEVEL :=
  7426.                         CURRENT_STATUS.CONTROL_NEST_LEVEL + 1;
  7427.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.CONTROL_NEST_LEVEL;
  7428.          NEW_NEST_REC.KIND_OF_NEST := CONTROL_NEST;
  7429.          NEW_NEST_REC.PARAMETERS   := 0;
  7430.          NEW_NEST_REC.START_TOKEN  := FROM_THIS_TOKEN;
  7431.  
  7432.      when TOKENIZER.DO_TOKEN =>
  7433. -------------------------------------------------------
  7434.         -- ACCEPT is the beginning of the block!
  7435. -------------------------------------------------------
  7436.          SEARCH_TOKEN := SEARCH_BACKWARD(FROM_THIS_TOKEN,
  7437.                                          TOKENIZER.ACCEPT_TOKEN);
  7438.          CURRENT_STATUS.CONTROL_NEST_LEVEL :=
  7439.                         CURRENT_STATUS.CONTROL_NEST_LEVEL + 1;
  7440.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.CONTROL_NEST_LEVEL;
  7441.          NEW_NEST_REC.KIND_OF_NEST := CONTROL_NEST;
  7442.          NEW_NEST_REC.PARAMETERS   := 0;
  7443.          NEW_NEST_REC.START_TOKEN  := SEARCH_TOKEN;
  7444.  
  7445.      when TOKENIZER.LOOP_TOKEN =>
  7446.          -- FOR or WHILE may be the beginning of the block!
  7447.          -- Find the appropriate (if any) FOR or WHILE token.
  7448.          SEARCH_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN( FROM_THIS_TOKEN );
  7449.          begin
  7450.              while not IS_STATEMENT( SEARCH_TOKEN ) loop
  7451.                 SEARCH_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN( SEARCH_TOKEN );
  7452.              end loop;
  7453.          exception
  7454.              when END_OF_TOKENS =>
  7455.                 null;
  7456.              when others =>
  7457.                 raise;
  7458.          end;
  7459.          CURRENT_STATUS.CONTROL_NEST_LEVEL :=
  7460.                         CURRENT_STATUS.CONTROL_NEST_LEVEL + 1;
  7461.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.CONTROL_NEST_LEVEL;
  7462.          NEW_NEST_REC.KIND_OF_NEST := CONTROL_NEST;
  7463.          NEW_NEST_REC.PARAMETERS   := 0;
  7464.          if TOKENIZER.TYPE_OF_TOKEN_IS(SEARCH_TOKEN)=TOKENIZER.WHILE_TOKEN or
  7465.             TOKENIZER.TYPE_OF_TOKEN_IS(SEARCH_TOKEN)=TOKENIZER.FOR_TOKEN then
  7466.                 NEW_NEST_REC.START_TOKEN  := SEARCH_TOKEN;
  7467.          else
  7468.                 NEW_NEST_REC.START_TOKEN  := FROM_THIS_TOKEN;
  7469.          end if;
  7470.  
  7471.      when TOKENIZER.THEN_TOKEN =>
  7472.         -- IF is the beginning of the block!
  7473.          SEARCH_TOKEN := SEARCH_BACKWARD(FROM_THIS_TOKEN,  TOKENIZER.IF_TOKEN);
  7474.          CURRENT_STATUS.CONTROL_NEST_LEVEL :=
  7475.                             CURRENT_STATUS.CONTROL_NEST_LEVEL + 1;
  7476.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.CONTROL_NEST_LEVEL;
  7477.          NEW_NEST_REC.KIND_OF_NEST := CONTROL_NEST;
  7478.          NEW_NEST_REC.PARAMETERS   := 0;
  7479.          NEW_NEST_REC.START_TOKEN  := SEARCH_TOKEN;
  7480.  
  7481.    -- Package
  7482.      when TOKENIZER.PACKAGE_TOKEN  =>
  7483.          CURRENT_STATUS.PACKAGE_NEST_LEVEL :=
  7484.                        CURRENT_STATUS.PACKAGE_NEST_LEVEL + 1;
  7485.          CURRENT_STATUS.IN_BODY := FALSE;
  7486.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.PACKAGE_NEST_LEVEL;
  7487.          NEW_NEST_REC.KIND_OF_NEST := PACKAGE_NEST;
  7488.          NEW_NEST_REC.PARAMETERS   := 0;
  7489.          NEW_NEST_REC.START_TOKEN  := FROM_THIS_TOKEN;
  7490.  
  7491.    -- Subprogram
  7492.      when TOKENIZER.FUNCTION_TOKEN |
  7493.        TOKENIZER.PROCEDURE_TOKEN =>
  7494.          CURRENT_STATUS.PROCEDURE_NEST_LEVEL :=
  7495.                        CURRENT_STATUS.PROCEDURE_NEST_LEVEL + 1;
  7496.          CURRENT_STATUS.IN_BODY := FALSE;
  7497.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.PROCEDURE_NEST_LEVEL;
  7498.          NEW_NEST_REC.KIND_OF_NEST := SUBPROGRAM_NEST;
  7499.          -- Find parameter list!
  7500.          HANDLE_PARAMETER_LIST( FROM_THIS_TOKEN, PARAM_COUNT );
  7501.          NEW_NEST_REC.PARAMETERS   := PARAM_COUNT;
  7502.          NEW_NEST_REC.START_TOKEN  := FROM_THIS_TOKEN;
  7503.  
  7504.      when TOKENIZER.TASK_TOKEN =>
  7505.         -- SUBPROGRAM?
  7506.          CURRENT_STATUS.PROCEDURE_NEST_LEVEL :=
  7507.                       CURRENT_STATUS.PROCEDURE_NEST_LEVEL + 1;
  7508.          CURRENT_STATUS.IN_BODY := FALSE;
  7509.          NEW_NEST_REC.LEVEL := CURRENT_STATUS.PROCEDURE_NEST_LEVEL;
  7510.          NEW_NEST_REC.KIND_OF_NEST := SUBPROGRAM_NEST;
  7511.          NEW_NEST_REC.PARAMETERS   := 0;
  7512.          NEW_NEST_REC.START_TOKEN  := FROM_THIS_TOKEN;
  7513.       when others => raise BAD_BLOCK_START;
  7514.     end case;
  7515.  
  7516.     -- Now check to see if nesting has exceeded maximum level
  7517.     case NEW_NEST_REC.KIND_OF_NEST is
  7518.       when SUBPROGRAM_NEST =>
  7519.          if CURRENT_STATUS.PROCEDURE_NEST_LEVEL >
  7520.             STYLE_PARAMETERS.SUBPROGRAM_NESTING_LEVEL then
  7521.                    REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,FROM_THIS_TOKEN,
  7522.                    SUBPROGRAM_NEST_EXCEEDED,
  7523.                    REPORT_GENERATOR.SUBPROGRAM_NESTED_TOO_DEEP);
  7524.                    STYLE_REPORT.SUBPROGRAM_NESTING_EXCEEDING_MAXIMUM :=
  7525.                      STYLE_REPORT.SUBPROGRAM_NESTING_EXCEEDING_MAXIMUM + 1;
  7526.          end if;
  7527.  
  7528.       when PACKAGE_NEST    =>
  7529.          if CURRENT_STATUS.PACKAGE_NEST_LEVEL >
  7530.             STYLE_PARAMETERS.PACKAGE_NESTING_LEVEL then
  7531.                REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,FROM_THIS_TOKEN,
  7532.                    PACKAGE_NEST_EXCEEDED,
  7533.                    REPORT_GENERATOR.PACKAGE_NESTED_TOO_DEEP);
  7534.                STYLE_REPORT.PACKAGE_NESTING_EXCEEDING_MAXIMUM :=
  7535.                    STYLE_REPORT.PACKAGE_NESTING_EXCEEDING_MAXIMUM + 1;
  7536.          end if;
  7537.  
  7538.       when CONTROL_NEST    =>
  7539.          if CURRENT_STATUS.CONTROL_NEST_LEVEL >
  7540.             STYLE_PARAMETERS.CONTROL_NESTING_LEVEL then
  7541.                REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,FROM_THIS_TOKEN,
  7542.                  CONTROL_NEST_EXCEEDED,
  7543.                  REPORT_GENERATOR.CONTROL_STRUCTURE_NESTED_TOO_DEEP);
  7544.                STYLE_REPORT.CONTROL_STRUCTURE_NESTING_EXCEEDING_MAXIMUM :=
  7545.                  STYLE_REPORT.CONTROL_STRUCTURE_NESTING_EXCEEDING_MAXIMUM + 1;
  7546.          end if;
  7547.        when HEADER         => null;
  7548.     end case;
  7549.  
  7550.     NEW_NEST_REC.EXITS := CURRENT_STATUS.EXITS_IN_LOOPS;
  7551.     CURRENT_STATUS.EXITS_IN_LOOPS := 0;
  7552.  
  7553.     -- Now push the Nesting record onto the stack!
  7554.     NEST_STACK.PUSH( NEW_NEST_REC, MISC_NEST_STACK );
  7555.  
  7556.  
  7557.  
  7558.  
  7559.     -- Tag current indent markers;
  7560.     CURRENT_STATUS.BEGIN_INDENT := true;
  7561.                   -- Flag indicating we're at the beginning of a block
  7562.  
  7563.  
  7564. exception
  7565.    when BAD_BLOCK_START =>
  7566.       TEXT_IO.NEW_LINE;
  7567.       TEXT_IO.PUT("Inside ENTERING_BLOCK -- exception:");
  7568.       TEXT_IO.PUT(" A bad start-of-block token has been sent!");
  7569.  
  7570.    when NEST_STACK.STACK_OVERFLOW =>
  7571.       REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE, FROM_THIS_TOKEN,
  7572.                                 OVERFLOW_MSG,
  7573.                                 REPORT_GENERATOR.UNMATCHED_NESTING);
  7574.  
  7575.    when NEST_STACK.STACK_UNDERFLOW =>
  7576.       REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE, FROM_THIS_TOKEN,
  7577.                                 UNDERFLOW_MSG,
  7578.                                 REPORT_GENERATOR.UNMATCHED_NESTING);
  7579.  
  7580.    when others =>
  7581.       TEXT_IO.NEW_LINE;
  7582.       TEXT_IO.PUT("Inside ENTERING_BLOCK -- exception:" );
  7583.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  7584.       TEXT_IO.PUT("While inside line:" );
  7585.       TOKENIZER.LINE_CONTAINING_TOKEN(FROM_THIS_TOKEN, SOURCE_LINE );
  7586.       TEXT_IO.PUT_LINE( DYN.STR( SOURCE_LINE ) );
  7587.  
  7588. end ENTERING_BLOCK_STRUCTURE;
  7589. ::::::::::
  7590. entering_sub_block.ada
  7591. ::::::::::
  7592. separate (STYLE_CHECKER)
  7593.  
  7594. procedure ENTERING_SUB_BLOCK_STRUCTURE(FROM_THIS_TOKEN : in TOKENIZER.TOKEN) is
  7595. -- ABSTRACT : This handles the case of intermediate levels of indentation
  7596. --            without really entering a complete block such as
  7597. --            the "else" within and if-then-else-endif statement.
  7598. -- PARAMETER: This token points to the RESERVED WORD which starts a sub-block
  7599.  
  7600.      OLD_NEST_REC : NESTING_RECORD;  -- for temporary POP!
  7601.  
  7602. begin
  7603.     -- All we have to do is allow the indentation to reset!
  7604.     CURRENT_STATUS.BEGIN_INDENT := true;
  7605.     NEST_STACK.POP( OLD_NEST_REC, MISC_NEST_STACK );
  7606.     -- Reset old indentation level!
  7607.     CURRENT_STATUS.CURRENT_INDENT := OLD_NEST_REC.INDENT;
  7608.     -- Restore nesting record!
  7609.     NEST_STACK.PUSH( OLD_NEST_REC, MISC_NEST_STACK );
  7610.  
  7611.     exception
  7612.         when others =>
  7613.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  7614.             TEXT_IO.PUT_LINE(" in ENTERING_SUB_BLOCK_STRUCTURE");
  7615.             raise;
  7616. end ENTERING_SUB_BLOCK_STRUCTURE;
  7617. ::::::::::
  7618. exiting_block.ada
  7619. ::::::::::
  7620.  
  7621. separate( STYLE_CHECKER )
  7622.  
  7623. procedure EXITING_BLOCK_STRUCTURE( FROM_THIS_TOKEN : in TOKENIZER.TOKEN ) is
  7624. -- ABSTRACT: This cleans up after blocks, and does checks on the block
  7625. --           which can now be done, i.e. loop name, size of block, etc.
  7626. --           blank lines before the block.
  7627. -- PARAMETERS: FROM_THIS_TOKEN is the token signifying the end of block.
  7628. --             This will likely be and "END" word.
  7629. -- ALGORITHM: Look to the Start of the block (The start token should be
  7630. --            on the NEST-Stack).
  7631. --            Figure out the number of statements in the structure (the
  7632. --            nest-record should have a partial count and add to this
  7633. --            the remainder statement count, including the 'end' statement.
  7634. --            Determine the kind of structure.  Record the size (counter)
  7635. --            For subprograms determine whether it is past the limit.
  7636. --            If Control-structure AND large-enough
  7637. --              Check presence of LOOP-NAMES, blank lines around
  7638. --              block.
  7639. --            Reset the indentation counts.
  7640. --            Reset the EXITs count if exiting a LOOP, FOR, or WHILE
  7641. --            Reset the IN_BODY flag if this is a package or subprogram
  7642.  
  7643. use TOKENIZER;
  7644. use STYLE_PARAMETERS;
  7645. package INT_IO is new TEXT_IO.INTEGER_IO( natural );
  7646.  
  7647. LOOKAROUND : TOKENIZER.TOKEN;
  7648. START_BLOCK_TOKEN : TOKENIZER.TOKEN;
  7649. TEMP_TOKEN_TYPE   : TOKENIZER.TOKEN_TYPE;
  7650. BLOCK_SIZE : natural;
  7651. OLD_NEST_REC : NESTING_RECORD;
  7652. LOOKBACK_NEST_REC : NESTING_RECORD;
  7653. SMALL_LIMIT : natural;
  7654. LARGE_LIMIT : natural;
  7655. SOURCE_LINE : DYN.DYN_STRING;
  7656. NO_BLANKS_FLAG : boolean := false;
  7657.  
  7658. SUBPROGRAM_TOO_SMALL    : constant string :=
  7659.      "This subprogram is smaller than the defined limits!";
  7660. SUBPROGRAM_TOO_LARGE    : constant string :=
  7661.      "This subprogram is larger than the defined limits!";
  7662. MISSING_NAME_MSG        : constant string :=
  7663.      "This structure is large enough that it should have a loop-name!";
  7664. NO_BEGINNING_BLANKS_MSG : constant string :=
  7665.      "This structure should have preceeding blank lines to set it off.";
  7666. NO_TRAILING_BLANKS_MSG  : constant string :=
  7667.      "This structure should have following blank lines to set it off.";
  7668. TOO_MANY_EXITS_MSG      : constant string :=
  7669.      "This loop has more EXITS than allowed by the style.";
  7670. UNDERFLOW_MSG           : constant string :=
  7671.  "Too many ENDs.  Check Ada syntax.  Otherwise we didn't catch a block enter!";
  7672.  
  7673. begin
  7674.    NEST_STACK.POP( OLD_NEST_REC, MISC_NEST_STACK );
  7675.    -- Reset to old indentation level
  7676.    CURRENT_STATUS.CURRENT_INDENT := OLD_NEST_REC.INDENT;
  7677.    CURRENT_STATUS.BEGIN_INDENT   := false; -- this should be redundant!
  7678.  
  7679.  
  7680.    -- Check for error in our nesting detection!
  7681.    if OLD_NEST_REC.KIND_OF_NEST = HEADER then
  7682.        -- Try to partially recover by dummying a header record!
  7683.        NEST_STACK.PUSH( OLD_NEST_REC, MISC_NEST_STACK );
  7684.        REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, FROM_THIS_TOKEN,
  7685.         UNDERFLOW_MSG,REPORT_GENERATOR.OTHER);
  7686.    end if;
  7687.  
  7688.    -- Determine the number of statements in the block
  7689.    -- NOTE! We may have to add one here to account for the 'end' statement
  7690.    -- depending on where we check for statements.
  7691.    BLOCK_SIZE := CURRENT_STATUS.CURRENT_STATEMENTS + OLD_NEST_REC.STATEMENTS;
  7692. -- if OLD_NEST_REC.KIND_OF_NEST = CONTROL_NEST then
  7693. --   TEXT_IO.NEW_LINE;
  7694. --   TEXT_IO.PUT("Exiting a control block of ");
  7695. --   INT_IO.PUT( BLOCK_SIZE );
  7696. --   TEXT_IO.PUT_LINE(" statements.");
  7697. -- else
  7698. --   TEXT_IO.NEW_LINE;
  7699. --   LOOKAROUND := NEXT_NON_TRIVIAL_TOKEN( FROM_THIS_TOKEN );
  7700. --   TEXT_IO.PUT("Exiting PACKAGE/SUBPROGRAM " &
  7701. --               DYN.STR(TOKENIZER.EXTERNAL_REPRESENTATION(LOOKAROUND))
  7702. --               & " of ");
  7703. --   INT_IO.PUT( BLOCK_SIZE );
  7704. --   TEXT_IO.PUT_LINE(" statements.");
  7705. -- end if;
  7706.  
  7707.    NEST_STACK.POP( LOOKBACK_NEST_REC, MISC_NEST_STACK );
  7708.    -- Update statement count for enclosing block!
  7709.    LOOKBACK_NEST_REC.STATEMENTS := LOOKBACK_NEST_REC.STATEMENTS + BLOCK_SIZE;
  7710.    CURRENT_STATUS.CURRENT_STATEMENTS := 0;
  7711.    -- Get last IN_BODY status!
  7712.    CURRENT_STATUS.IN_BODY := LOOKBACK_NEST_REC.IN_BODY;
  7713.    -- Restore updated nest-record
  7714.    NEST_STACK.PUSH( LOOKBACK_NEST_REC, MISC_NEST_STACK );
  7715.  
  7716.    -- Find beginning of loop
  7717.    START_BLOCK_TOKEN := OLD_NEST_REC.START_TOKEN;
  7718.  
  7719.    -- Is this loop of significant size?
  7720.    if BLOCK_SIZE > STYLE_PARAMETERS.SMALL_STRUCTURE_SIZE  then
  7721.      ----------------------------------------
  7722.      -- Check for blank lines before the loop.
  7723.      ----------------------------------------
  7724.      -- check preceeding blank line
  7725.      declare
  7726.        PREV_TYPE : TOKENIZER.TOKEN_TYPE;
  7727.      begin -- for overrunning beginning of tokens!
  7728.         LOOKAROUND := SEARCH_BACKWARD( START_BLOCK_TOKEN,TOKENIZER.END_OF_LINE);
  7729.         -- End of previous line.  If this is the only token on the line,
  7730.         -- then this is a blank line and it is O.K.
  7731.         --   NOTE:  Is a comment equivalent to a blank line?
  7732.         --   For now, comments or 'withs' are o.k.
  7733.         PREV_TYPE := TOKENIZER.TYPE_OF_TOKEN_IS(
  7734.                      PREVIOUS_TOKEN( LOOKAROUND ));
  7735.         if PREV_TYPE /= TOKENIZER.END_OF_LINE and
  7736.            PREV_TYPE /= TOKENIZER.COMMENT     then
  7737.            -- look for with's!  (USE is NOT acceptable)
  7738.            LOOKAROUND := SEARCH_BACKWARD( LOOKAROUND,TOKENIZER.END_OF_LINE);
  7739.            LOOKAROUND := TOKENIZER.NEXT_TOKEN(LOOKAROUND);
  7740.            if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAROUND) = TOKENIZER.WITH_TOKEN or
  7741.             (TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAROUND) = TOKENIZER.IDENTIFIER and
  7742.             (TOKENIZER.TYPE_OF_TOKEN_IS(NEXT_TOKEN(LOOKAROUND)) =
  7743.              TOKENIZER.COLON) and
  7744.             (TOKENIZER.TYPE_OF_TOKEN_IS(NEXT_TOKEN(NEXT_TOKEN(LOOKAROUND))) =
  7745.              TOKENIZER.END_OF_LINE) ) then
  7746.  
  7747.                null;
  7748.            else
  7749.                 REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START_BLOCK_TOKEN,
  7750.                   NO_BEGINNING_BLANKS_MSG,
  7751.                   REPORT_GENERATOR.MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK);
  7752.                 NO_BLANKS_FLAG := true;
  7753.            end if;
  7754.         end if;
  7755.  
  7756.      exception
  7757.         when END_OF_TOKENS =>   -- at beginning of tokens
  7758.                                 -- this shouldn't occur but is is acceptable.
  7759.                 null;
  7760.         when others =>
  7761.                 raise;
  7762.      end;
  7763.  
  7764.      -- check following  blank line
  7765.      begin -- for overrunning beginning of tokens!
  7766.         LOOKAROUND := SEARCH_FORWARD ( START_BLOCK_TOKEN,TOKENIZER.END_OF_LINE);
  7767.         -- End of this line.  If the next token is END_OF_TOKEN
  7768.         -- then this is a blank line and it is O.K.
  7769.         --   NOTE:  Is a comment equivalent to a blank line?
  7770.         if TOKENIZER.TYPE_OF_TOKEN_IS(TOKENIZER.NEXT_TOKEN (LOOKAROUND ))
  7771.            /= TOKENIZER.END_OF_LINE then
  7772.            REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START_BLOCK_TOKEN,
  7773.                 NO_TRAILING_BLANKS_MSG,
  7774.                 REPORT_GENERATOR.MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK);
  7775.            NO_BLANKS_FLAG := true;
  7776.         end if;
  7777.      exception
  7778.         when END_OF_TOKENS =>   -- at end of tokens
  7779.                                 -- this shouldn't occur but is is acceptable.
  7780.                 null;
  7781.         when others =>
  7782.                 raise;
  7783.      end;
  7784.  
  7785.      if NO_BLANKS_FLAG then
  7786.         STYLE_REPORT.MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK :=
  7787.         STYLE_REPORT.MISSING_BLANK_LINES_TO_SET_OFF_A_BLOCK + 1;
  7788.      end if;
  7789.  
  7790.  
  7791.      -- If this is a 'loop' (including for, and while).  If so
  7792.      -- check for loop names!
  7793.      -- and the number of exits!
  7794.      TEMP_TOKEN_TYPE := TOKENIZER.TYPE_OF_TOKEN_IS(START_BLOCK_TOKEN);
  7795.      if TEMP_TOKEN_TYPE = TOKENIZER.LOOP_TOKEN or
  7796.         TEMP_TOKEN_TYPE = TOKENIZER.FOR_TOKEN or
  7797.         TEMP_TOKEN_TYPE = TOKENIZER.WHILE_TOKEN  then
  7798.  
  7799.         if STYLE_PARAMETERS.LOOP_NAME_REQUIRED /=
  7800.            STYLE_PARAMETERS.NOT_REQUIRED then
  7801.            -- Check loop names
  7802.            LOOKAROUND := PREVIOUS_NON_TRIVIAL_TOKEN( START_BLOCK_TOKEN );
  7803.            if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAROUND) /=
  7804.                         TOKENIZER.LEFT_LABEL_BRACKET then
  7805.                 REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START_BLOCK_TOKEN,
  7806.                                            MISSING_NAME_MSG,
  7807.                                            REPORT_GENERATOR.LOOP_WITHOUT_NAME);
  7808.                 STYLE_REPORT.LOOPS_WITHOUT_NAMES :=
  7809.                    STYLE_REPORT.LOOPS_WITHOUT_NAMES + 1;
  7810.            end if;
  7811.         end if;
  7812.  
  7813.         -- Check number of exits!
  7814.         if CURRENT_STATUS.EXITS_IN_LOOPS >
  7815.            STYLE_PARAMETERS.NUMBER_OF_LOOP_EXITS then
  7816.              REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START_BLOCK_TOKEN,
  7817.                                         TOO_MANY_EXITS_MSG,
  7818.                                         REPORT_GENERATOR.TOO_MANY_EXITS);
  7819.              STYLE_REPORT.INSTANCES_OF_TOO_MANY_EXITS :=
  7820.                 STYLE_REPORT.INSTANCES_OF_TOO_MANY_EXITS + 1;
  7821.         end if;
  7822.         -- reset "exits" counter
  7823.         -- This many not cover all the situations, but with good Ada
  7824.         -- input it should work
  7825.         CURRENT_STATUS.EXITS_IN_LOOPS := OLD_NEST_REC.EXITS;
  7826.  
  7827.      end if;
  7828.  
  7829.    end if;
  7830.  
  7831.    -- If in a Package-block then
  7832.    if OLD_NEST_REC.KIND_OF_NEST = PACKAGE_NEST then
  7833.       CURRENT_STATUS.CURRENT_TRAIL_COMMENT_INDENT := 0;
  7834.    end if;
  7835.  
  7836.    -- If a Subprogram-block then
  7837.    if OLD_NEST_REC.KIND_OF_NEST = SUBPROGRAM_NEST then
  7838.       CURRENT_STATUS.CURRENT_TRAIL_COMMENT_INDENT := 0;
  7839.       -- Check for the limits on subprogram size
  7840.       STYLE_PARAMETERS.AVERAGE_SUBPROGRAM_SIZE (SMALL_LIMIT, LARGE_LIMIT);
  7841.       if BLOCK_SIZE < SMALL_LIMIT then
  7842.          REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START_BLOCK_TOKEN,
  7843.                 SUBPROGRAM_TOO_SMALL,
  7844.                 REPORT_GENERATOR.SUBPROGRAM_SIZE_BELOW_MINIMUM);
  7845.          STYLE_REPORT.INSTANCES_OF_SIZE_BELOW_MINIMUM :=
  7846.             STYLE_REPORT.INSTANCES_OF_SIZE_BELOW_MINIMUM + 1;
  7847.       elsif BLOCK_SIZE > LARGE_LIMIT then
  7848.          REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, START_BLOCK_TOKEN,
  7849.                 SUBPROGRAM_TOO_LARGE,
  7850.                 REPORT_GENERATOR.SUBPROGRAM_SIZE_ABOVE_MAXIMUM);
  7851.          STYLE_REPORT.INSTANCES_OF_SIZE_ABOVE_MAXIMUM :=
  7852.             STYLE_REPORT.INSTANCES_OF_SIZE_ABOVE_MAXIMUM + 1;
  7853.       end if;
  7854.    end if;
  7855.  
  7856.    -- Update the nexting counter
  7857.    case OLD_NEST_REC.KIND_OF_NEST is
  7858.      when PACKAGE_NEST =>
  7859.         CURRENT_STATUS.PACKAGE_NEST_LEVEL :=
  7860.           CURRENT_STATUS.PACKAGE_NEST_LEVEL - 1;
  7861.      when SUBPROGRAM_NEST =>
  7862.         CURRENT_STATUS.PROCEDURE_NEST_LEVEL :=
  7863.           CURRENT_STATUS.PROCEDURE_NEST_LEVEL - 1;
  7864.      when CONTROL_NEST =>
  7865.         CURRENT_STATUS.CONTROL_NEST_LEVEL :=
  7866.           CURRENT_STATUS.CONTROL_NEST_LEVEL - 1;
  7867.      when others =>
  7868.        null;
  7869.    end case;
  7870.  
  7871.  
  7872. exception
  7873.  
  7874.    when others =>
  7875.       TEXT_IO.NEW_LINE;
  7876.       TEXT_IO.PUT("Inside EXITING_BLOCK_STRUCTURE   -- exception:" );
  7877.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  7878.       TEXT_IO.PUT_LINE("While inside line:");
  7879.       TOKENIZER.LINE_CONTAINING_TOKEN(FROM_THIS_TOKEN, SOURCE_LINE );
  7880.       TEXT_IO.PUT_LINE( DYN.STR( SOURCE_LINE ) );
  7881.  
  7882. end EXITING_BLOCK_STRUCTURE;
  7883. ::::::::::
  7884. get_next_token.ada
  7885. ::::::::::
  7886. separate (STYLE_CHECKER)
  7887.  
  7888. function GET_NEXT_TOKEN_AND_UPDATE_COUNT return TOKENIZER.TOKEN is
  7889. --------------------------------------------------------------------------
  7890. -- Abstract   : This function gets the next "uncounted" token from the
  7891. --              token stream and updates neccessary count information.
  7892. --------------------------------------------------------------------------
  7893.  
  7894. begin
  7895.     if CURRENT_STATUS.CURRENT_LINE = 0 then
  7896.         CURRENT_STATUS.CURRENT_TOKEN := TOKENIZER.FIRST_TOKEN;
  7897.         CURRENT_STATUS.CURRENT_LINE := 1;
  7898.     else
  7899.         CURRENT_STATUS.CURRENT_TOKEN :=
  7900.             TOKENIZER.NEXT_TOKEN(CURRENT_STATUS.CURRENT_TOKEN);
  7901.     end if;
  7902.     STYLE_REPORT.TOKEN_COUNT(
  7903.         TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_STATUS.CURRENT_TOKEN)) :=
  7904.         STYLE_REPORT.TOKEN_COUNT(
  7905.         TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_STATUS.CURRENT_TOKEN)) + 1;
  7906.     return CURRENT_STATUS.CURRENT_TOKEN;
  7907.     exception
  7908.         when TOKENIZER.END_OF_TOKENS =>
  7909.             raise;
  7910.         when others =>
  7911.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  7912.             TEXT_IO.PUT_LINE(" in GET_NEXT_TOKEN_AND_UPDATE_COUNT");
  7913.             raise;
  7914. end GET_NEXT_TOKEN_AND_UPDATE_COUNT;
  7915. ::::::::::
  7916. is_statement.ada
  7917. ::::::::::
  7918.  
  7919. separate (STYLE_CHECKER)
  7920.  
  7921. function IS_STATEMENT(EXAMINED_TOKEN : in TOKENIZER.TOKEN) return boolean is
  7922. -- Determine whether or not this token is the start of a statement.
  7923. -- Cases: If it is one of the following reserved words:
  7924. --     IF (not after an END), END, FOR, USE (except rep specs),
  7925. --     CASE (not after an 'END'), EXIT, GOTO, LOOP (not after an 'END'), TASK,
  7926. --     TYPE, WITH, ABORT, BEGIN, DELAY, ENTRY, RAISE, WHILE, ACCEPT,
  7927. --     PRAGMA, RETURN (not in a function declaration!),
  7928. --     SELECT (not after an 'END'), PACKAGE, SUBTYPE, FUNCTION,
  7929. --     EXCEPTION, PROCEDURE, TERMINATE.
  7930. -- If the token is an IDENTIFIER
  7931. -- AND
  7932. --    The previous (significant) token is:
  7933. --    ;  =>  >>  SELECT, THEN, ELSE, DO, IS, RECORD, OTHERS;
  7934. -- AND
  7935. --    This is not in a (..) pair (in this case this is a parameter declaration)
  7936. -- THEN
  7937. --    The token IS A STATEMENT start.
  7938.  
  7939. use TOKENIZER;
  7940. LOOKAHEAD : TOKENIZER.TOKEN;
  7941.  
  7942. begin -- IS_STATEMENT
  7943.  begin
  7944.  
  7945.    case TOKENIZER.TYPE_OF_TOKEN_IS(EXAMINED_TOKEN) is
  7946.        when IF_TOKEN =>
  7947.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  7948.              if TOKENIZER.TYPE_OF_TOKEN_IS
  7949.                 (LOOKAHEAD) /= TOKENIZER.END_TOKEN then
  7950.                 return true;
  7951.              else
  7952.                 return false;
  7953.              end if;
  7954.        when END_TOKEN => return true;
  7955.        when FOR_TOKEN => return true;
  7956.        when USE_TOKEN => -- except rep specs
  7957.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  7958.              return TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) /=
  7959.                     TOKENIZER.IDENTIFIER;
  7960.        when CASE_TOKEN => -- not after an 'end'
  7961.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  7962.              if TOKENIZER.TYPE_OF_TOKEN_IS
  7963.                 (LOOKAHEAD) /= TOKENIZER.END_TOKEN then
  7964.                 return true;
  7965.              else
  7966.                 return false;
  7967.              end if;
  7968.        when EXIT_TOKEN => return true;
  7969.        when GOTO_TOKEN =>  return true;
  7970.        when LOOP_TOKEN => -- not after an 'end'
  7971.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  7972.              if TOKENIZER.TYPE_OF_TOKEN_IS
  7973.                 (LOOKAHEAD) /= TOKENIZER.END_TOKEN then
  7974.                 return true;
  7975.              else
  7976.                 return false;
  7977.              end if;
  7978.        when TASK_TOKEN =>  return true;
  7979.        when TYPE_TOKEN =>  return true;
  7980.        when WITH_TOKEN =>  return true;
  7981.        when ABORT_TOKEN =>  return true;
  7982.        when BEGIN_TOKEN =>  return true;
  7983.        when DELAY_TOKEN =>  return true;
  7984.        when ENTRY_TOKEN =>  return true;
  7985.        when RAISE_TOKEN =>  return true;
  7986.        when WHILE_TOKEN =>  return true;
  7987.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  7988.              if TOKENIZER.TYPE_OF_TOKEN_IS
  7989.                   (LOOKAHEAD) /= TOKENIZER.END_TOKEN then
  7990.                 return true;
  7991.              else
  7992.                 return false;
  7993.              end if;
  7994.        when ACCEPT_TOKEN =>  return true;
  7995.        when PRAGMA_TOKEN =>  return true;
  7996. --                    when RECORD_TOKEN =>
  7997.        when RETURN_TOKEN =>
  7998.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  7999.              if TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) /=
  8000.                  TOKENIZER.RIGHT_PARENTHESIS and
  8001.                 TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) /=
  8002.                  TOKENIZER.IDENTIFIER        then
  8003.                 return true;
  8004.              else
  8005.                 return false;
  8006.              end if;
  8007.  
  8008.        when SELECT_TOKEN =>
  8009.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  8010.              return TOKENIZER.TYPE_OF_TOKEN_IS ( LOOKAHEAD )
  8011.                  /= TOKENIZER.END_TOKEN;
  8012.        when PACKAGE_TOKEN =>  return true;
  8013.        when SUBTYPE_TOKEN =>  return true;
  8014.        when FUNCTION_TOKEN =>  return true;
  8015.        when SEPARATE_TOKEN =>
  8016.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  8017.              -- if declaration -> X : exception; -- then not a statement!
  8018.              return TOKENIZER.TYPE_OF_TOKEN_IS ( LOOKAHEAD )
  8019.                  /= TOKENIZER.IS_TOKEN;
  8020.        when EXCEPTION_TOKEN =>
  8021.              LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  8022.              -- if declaration -> X : exception; -- then not a statement!
  8023.              return TOKENIZER.TYPE_OF_TOKEN_IS ( LOOKAHEAD )
  8024.                  /= TOKENIZER.COLON;
  8025.        when PROCEDURE_TOKEN =>  return true;
  8026.        when TERMINATE_TOKEN =>  return true;
  8027.  
  8028.        when IDENTIFIER |
  8029.             NULL_TOKEN =>
  8030.              if LEFT_PARENTHESIS = TOKENIZER.TYPE_OF_TOKEN_IS(
  8031.                                    SEARCH_BACKWARD_FOR_ONE_OF(EXAMINED_TOKEN,
  8032.                                            TOKENIZER.RIGHT_PARENTHESIS,
  8033.                                            TOKENIZER.LEFT_PARENTHESIS) ) then
  8034.                 return false;       -- Inside (..), i.e. parameter declaration
  8035.              else
  8036.                 -- look at the last token
  8037.                 LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(EXAMINED_TOKEN);
  8038.                 case TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) is
  8039.                    when TOKENIZER.SEMICOLON | TOKENIZER.ARROW |
  8040.                         TOKENIZER.RIGHT_LABEL_BRACKET |
  8041.                         TOKENIZER.DO_TOKEN     | TOKENIZER.BEGIN_TOKEN |
  8042.                         TOKENIZER.RECORD_TOKEN | TOKENIZER.OTHERS_TOKEN =>
  8043.                                   return TRUE;
  8044.                    when TOKENIZER.ELSE_TOKEN =>
  8045.                         LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(LOOKAHEAD);
  8046.                         -- OR ELSE identifier is NOT a statement!
  8047.                         return TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) /=
  8048.                                TOKENIZER.OR_TOKEN;
  8049.                    when TOKENIZER.THEN_TOKEN =>
  8050.                         LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(LOOKAHEAD);
  8051.                         -- AND ELSE identifier is NOT a statement!
  8052.                         return TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) /=
  8053.                                TOKENIZER.AND_TOKEN;
  8054.                    when TOKENIZER.LOOP_TOKEN |
  8055.                         TOKENIZER.SELECT_TOKEN =>
  8056.                         -- could be "end loop identifier"
  8057.                         LOOKAHEAD := PREVIOUS_NON_TRIVIAL_TOKEN(LOOKAHEAD);
  8058.                         return TOKENIZER.TYPE_OF_TOKEN_IS(LOOKAHEAD) /=
  8059.                                TOKENIZER.END_TOKEN;
  8060.                    when TOKENIZER.IS_TOKEN =>
  8061.                         -- true only if at begin of declarations!
  8062.                         return CURRENT_STATUS.BEGIN_INDENT
  8063.                                and not CURRENT_STATUS.IN_BODY;
  8064.                    when others =>
  8065.                                   return false;
  8066.                 end case;
  8067.              end if;
  8068.  
  8069.        when others => return false;
  8070.    end case;
  8071.  
  8072.     exception
  8073.         when END_OF_TOKENS =>
  8074.             return TRUE;
  8075.         when others =>
  8076.             raise;
  8077.  end;
  8078. exception
  8079.         when others =>
  8080.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  8081.             TEXT_IO.PUT_LINE(" in IS_STATEMENT");
  8082.             raise;
  8083. end IS_STATEMENT;
  8084. ::::::::::
  8085. literal.ada
  8086. ::::::::::
  8087. separate (STYLE_CHECKER)
  8088.  
  8089. procedure LITERAL_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN) is
  8090. --------------------------------------------------------------------------
  8091. -- Abstract   : This procedure is called when a literal token is encountered.
  8092. --------------------------------------------------------------------------
  8093. -- Parameters : FROM_THIS_TOKEN - token that is a literal
  8094. --------------------------------------------------------------------------
  8095. -- Algorithm  : Update the count of literals
  8096. --              If in a body update literal size information
  8097. --------------------------------------------------------------------------
  8098.  
  8099. begin
  8100.         CURRENT_STATUS.LITERAL_INFORMATION.NUMBER_OF_ITEMS :=
  8101.           CURRENT_STATUS.LITERAL_INFORMATION.NUMBER_OF_ITEMS + 1;
  8102.         if CURRENT_STATUS.IN_BODY then
  8103.            CURRENT_STATUS.LITERAL_INFORMATION.TOTAL_SIZE_OF_ITEMS :=
  8104.               CURRENT_STATUS.LITERAL_INFORMATION.TOTAL_SIZE_OF_ITEMS + 1;
  8105.         end if;
  8106.  
  8107.     exception
  8108.         when others =>
  8109.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  8110.             TEXT_IO.PUT_LINE(" in LITERAL_ENCOUNTERED");
  8111.             raise;
  8112. end LITERAL_ENCOUNTERED;
  8113. ::::::::::
  8114. new_line_token.ada
  8115. ::::::::::
  8116. separate (STYLE_CHECKER)
  8117.  
  8118. procedure NEW_LINE_TOKEN_ENCOUNTERED(FROM_THIS_TOKEN : in TOKENIZER.TOKEN) is
  8119. --------------------------------------------------------------------------
  8120. -- Abstract   : This procedure is called when an end of line token is
  8121. --              encountered.
  8122. --------------------------------------------------------------------------
  8123. -- Parameters : FROM_THIS_TOKEN - Token that is an end of line
  8124. --------------------------------------------------------------------------
  8125. -- Algorithm  : Check the line length and output an error message if
  8126. --                      neccessary.
  8127. --------------------------------------------------------------------------
  8128.  
  8129.     LINE        : TOKENIZER.LINE_NUM_RANGE;
  8130.     COLUMN      : TOKENIZER.LINE_INDEX_RANGE;
  8131. begin
  8132.     TOKENIZER.TOKEN_POSITION(FROM_THIS_TOKEN,LINE,COLUMN);
  8133.     if COLUMN > STYLE_PARAMETERS.LINE_SIZE then
  8134.         REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,FROM_THIS_TOKEN,
  8135.             "This line exceeds maximum line length",
  8136.             REPORT_GENERATOR.LINE_EXCEEDING_LINE_LENGTH);
  8137.         STYLE_REPORT.NUMBER_OF_LINES_EXCEEDING_LINE_LENGTH :=
  8138.             STYLE_REPORT.NUMBER_OF_LINES_EXCEEDING_LINE_LENGTH + 1;
  8139.     end if;
  8140.     exception
  8141.         when others =>
  8142.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  8143.             TEXT_IO.PUT_LINE(" in NEW_LINE_TOKEN_ENCOUNTERED");
  8144.             raise;
  8145. end NEW_LINE_TOKEN_ENCOUNTERED;
  8146. ::::::::::
  8147. non_trivial_token.ada
  8148. ::::::::::
  8149. separate (STYLE_CHECKER)
  8150.  
  8151. function PREVIOUS_NON_TRIVIAL_TOKEN(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  8152.     return TOKENIZER.TOKEN is
  8153. --------------------------------------------------------------------------
  8154. -- Abstract   : This function gets the last "non-trivial" token from the
  8155. --              input token.
  8156. --------------------------------------------------------------------------
  8157. -- Parameters : FROM_THIS_TOKEN - starting point in search for a "non-trivial"
  8158. --                                token.
  8159. --------------------------------------------------------------------------
  8160. -- Algorithm  : Starting at input token, go backward in token stream until
  8161. --                 a token that is not considered trivial is encountered.
  8162. --                 Specifically, trivial tokens are end_of_lines, comments,
  8163. --                      end_of_files, and garbage characters
  8164. --------------------------------------------------------------------------
  8165.  
  8166. use TOKENIZER;
  8167.  
  8168.     RETURN_TOKEN : TOKENIZER.TOKEN;
  8169.  
  8170. begin
  8171.         RETURN_TOKEN := TOKENIZER.PREVIOUS_TOKEN(FROM_THIS_TOKEN);
  8172.         while (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) = TOKENIZER.COMMENT)
  8173.           or (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) = TOKENIZER.END_OF_LINE)
  8174.           or (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) = TOKENIZER.END_OF_FILE)
  8175.           or (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) =
  8176.                 TOKENIZER.ANYTHING_ELSE)
  8177.             loop
  8178.                 RETURN_TOKEN := TOKENIZER.PREVIOUS_TOKEN(RETURN_TOKEN);
  8179.             end loop;
  8180.         return RETURN_TOKEN;
  8181.     exception
  8182.         when TOKENIZER.END_OF_TOKENS => raise;
  8183.         when others =>
  8184.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  8185.             TEXT_IO.PUT_LINE(" in PREVIOUS_NON_TRIVIAL_TOKEN");
  8186.             raise;
  8187. end PREVIOUS_NON_TRIVIAL_TOKEN;
  8188.  
  8189. separate (STYLE_CHECKER)
  8190.  
  8191.  
  8192. function NEXT_NON_TRIVIAL_TOKEN(FROM_THIS_TOKEN : in TOKENIZER.TOKEN)
  8193.     return TOKENIZER.TOKEN is
  8194. --------------------------------------------------------------------------
  8195. -- Abstract   : This function gets the next "non-trivial" token from the
  8196. --              input token.
  8197. --------------------------------------------------------------------------
  8198. -- Parameters : FROM_THIS_TOKEN - starting point in search for a "non-trivial"
  8199. --                                token.
  8200. --------------------------------------------------------------------------
  8201. -- Algorithm  : Starting at input token, go forward in token stream until
  8202. --                 a token that is not considered trivial is encountered.
  8203. --                 Specifically, trivial tokens are end_of_lines, comments,
  8204. --                      end_of_files, and garbage characters
  8205. --------------------------------------------------------------------------
  8206.  
  8207. use TOKENIZER;
  8208.  
  8209.     RETURN_TOKEN : TOKENIZER.TOKEN;
  8210.  
  8211. begin
  8212.         RETURN_TOKEN := TOKENIZER.NEXT_TOKEN(FROM_THIS_TOKEN);
  8213.         while (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) = TOKENIZER.COMMENT)
  8214.           or (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) = TOKENIZER.END_OF_LINE)
  8215.           or (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) = TOKENIZER.END_OF_FILE)
  8216.           or (TOKENIZER.TYPE_OF_TOKEN_IS(RETURN_TOKEN) =
  8217.                 TOKENIZER.ANYTHING_ELSE)
  8218.             loop
  8219.                 RETURN_TOKEN := TOKENIZER.NEXT_TOKEN(RETURN_TOKEN);
  8220.             end loop;
  8221.         return RETURN_TOKEN;
  8222.     exception
  8223.         when TOKENIZER.END_OF_TOKENS => raise;
  8224.         when others =>
  8225.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  8226.             TEXT_IO.PUT_LINE(" in NEXT_NON_TRIVIAL_TOKEN");
  8227.             raise;
  8228. end NEXT_NON_TRIVIAL_TOKEN;
  8229. ::::::::::
  8230. object_name.ada
  8231. ::::::::::
  8232. separate (STYLE_CHECKER)
  8233.  
  8234. procedure OBJECT_NAME_ENCOUNTERED(OBJECT_NAME_TOKEN : in TOKENIZER.TOKEN) is
  8235. --------------------------------------------------------------------------
  8236. -- Abstract   : This procedure is called when an object_name token is
  8237. --              encountered.
  8238. --------------------------------------------------------------------------
  8239. -- Parameters : OBJECT_NAME_TOKEN - token that is an object_name
  8240. --------------------------------------------------------------------------
  8241. -- Algorithm  : Check case of object name and output error message if
  8242. --                      neccessary.
  8243. --------------------------------------------------------------------------
  8244.  
  8245.     PHYSICAL_REPRESENTATION     : DYN.DYN_STRING :=
  8246.         TOKENIZER.EXTERNAL_REPRESENTATION(OBJECT_NAME_TOKEN);
  8247.  
  8248.     function CASELESS_CHAR( CHAR : in CHARACTER ) return boolean is
  8249.     -- This function checks for characters which should not effect
  8250.     -- the case of a name.
  8251.     -- This includes underscore '_' and numerics.
  8252.     begin
  8253.         return (CHAR = '_') or (CHAR >= '0' and CHAR <= '9');
  8254.     end CASELESS_CHAR;
  8255.  
  8256. begin
  8257.     -- Check case of object name
  8258.     case CURRENT_STATUS.CASE_OF_OBJECT_NAMES is
  8259.         when STYLE_PARAMETERS.NAME_CASE_UPPER =>
  8260.             for I in 1..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8261.                 if ((DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'A') or
  8262.                    (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'Z')) and
  8263.                 not CASELESS_CHAR(DYN.STR(PHYSICAL_REPRESENTATION)(I)) then
  8264.                     REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,OBJECT_NAME_TOKEN,
  8265.                         "Object name " & DYN.STR(PHYSICAL_REPRESENTATION) &
  8266.                         " should be in upper case",
  8267.                         REPORT_GENERATOR.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER);
  8268.                     STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER :=
  8269.                         STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER + 1;
  8270.                     exit;
  8271.                 end if;
  8272.             end loop;
  8273.         when STYLE_PARAMETERS.NAME_CASE_LOWER =>
  8274.             for I in 1..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8275.                 if ((DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'a') or
  8276.                    (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'z')) and
  8277.                 not CASELESS_CHAR(DYN.STR(PHYSICAL_REPRESENTATION)(I)) then
  8278.                     REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,OBJECT_NAME_TOKEN,
  8279.                         "Object name " & DYN.STR(PHYSICAL_REPRESENTATION) &
  8280.                         " should be in lower case",
  8281.                         REPORT_GENERATOR.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER);
  8282.                     STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER :=
  8283.                         STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER + 1;
  8284.                     exit;
  8285.                 end if;
  8286.             end loop;
  8287.         when STYLE_PARAMETERS.NAME_CASE_CONSISTANT =>
  8288.         --  This will only be selected if this is the first object name
  8289.         --  encountered, in which case it will be used to decide which case
  8290.         --  to use.
  8291.             if (DYN.STR(PHYSICAL_REPRESENTATION)(1) >= 'a') and
  8292.                (DYN.STR(PHYSICAL_REPRESENTATION)(1) <= 'z') then
  8293.                 CURRENT_STATUS.CASE_OF_OBJECT_NAMES :=
  8294.                     STYLE_PARAMETERS.NAME_CASE_LOWER;
  8295.                 for I in 2..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8296.                     if ((DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'a') or
  8297.                        (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'z')) and
  8298.                    not CASELESS_CHAR(DYN.STR(PHYSICAL_REPRESENTATION)(I)) then
  8299.                         CURRENT_STATUS.CASE_OF_OBJECT_NAMES :=
  8300.                     STYLE_PARAMETERS.NAME_CASE_ANY;
  8301.                         exit;
  8302.                     end if;
  8303.                 end loop;
  8304.             elsif (DYN.STR(PHYSICAL_REPRESENTATION)(2) >= 'a') and
  8305.                (DYN.STR(PHYSICAL_REPRESENTATION)(2) <= 'z') then
  8306.                 CURRENT_STATUS.CASE_OF_OBJECT_NAMES :=
  8307.                     STYLE_PARAMETERS.NAME_CASE_FIRST_CAPITALIZED;
  8308.                 for I in 3..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8309.                     if ((DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'a') or
  8310.                        (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'z')) and
  8311.                    not CASELESS_CHAR(DYN.STR(PHYSICAL_REPRESENTATION)(I)) then
  8312.                         CURRENT_STATUS.CASE_OF_OBJECT_NAMES :=
  8313.                         STYLE_PARAMETERS.NAME_CASE_ANY;
  8314.                         exit;
  8315.                     end if;
  8316.                 end loop;
  8317.             else
  8318.                 CURRENT_STATUS.CASE_OF_OBJECT_NAMES :=
  8319.                     STYLE_PARAMETERS.NAME_CASE_UPPER;
  8320.                 for I in 2..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8321.                     if ((DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'A') or
  8322.                        (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'Z')) and
  8323.                    not CASELESS_CHAR(DYN.STR(PHYSICAL_REPRESENTATION)(I)) then
  8324.                         CURRENT_STATUS.CASE_OF_OBJECT_NAMES :=
  8325.                         STYLE_PARAMETERS.NAME_CASE_ANY;
  8326.                         exit;
  8327.                     end if;
  8328.                 end loop;
  8329.             end if;
  8330.         when STYLE_PARAMETERS.NAME_CASE_FIRST_CAPITALIZED =>
  8331.             if ((DYN.STR(PHYSICAL_REPRESENTATION)(1) < 'A') or
  8332.                (DYN.STR(PHYSICAL_REPRESENTATION)(1) > 'Z')) then
  8333.                 REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,OBJECT_NAME_TOKEN,
  8334.                     "Object name " & DYN.STR(PHYSICAL_REPRESENTATION) &
  8335.                     " should have first character capitalized ",
  8336.                     REPORT_GENERATOR.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER);
  8337.                 STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER :=
  8338.                     STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER + 1;
  8339.             else
  8340.                 for I in 1..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8341.                     if ((DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'A') or
  8342.                        (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'Z')) and
  8343.                    not CASELESS_CHAR(DYN.STR(PHYSICAL_REPRESENTATION)(I)) then
  8344.                        REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,OBJECT_NAME_TOKEN,
  8345.                            "Object name " & DYN.STR(PHYSICAL_REPRESENTATION) &
  8346.                            " should have all but first character in lower" &
  8347.                            " case",
  8348.                         REPORT_GENERATOR.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER);
  8349.                         STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER :=
  8350.                             STYLE_REPORT.INVALID_CASE_FOR_AN_OBJECT_IDENTIFIER
  8351.                             + 1;
  8352.                        exit;
  8353.                     end if;
  8354.                 end loop;
  8355.             end if;
  8356.         when STYLE_PARAMETERS.NAME_CASE_ANY => null;
  8357.     end case;
  8358.     exception
  8359.         when others =>
  8360.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  8361.             TEXT_IO.PUT_LINE(" in OBJECT_NAME_ENCOUNTERED");
  8362.             raise;
  8363. end OBJECT_NAME_ENCOUNTERED;
  8364. ::::::::::
  8365. reserve_word.ada
  8366. ::::::::::
  8367. separate (STYLE_CHECKER)
  8368.  
  8369. procedure RESERVE_WORD_ENCOUNTERED(RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN) is
  8370. --------------------------------------------------------------------------
  8371. -- Abstract   : This procedure handles reserve word tokens.
  8372. --------------------------------------------------------------------------
  8373. -- Parameters : RESERVE_WORD_TOKEN - token that is a reserve_word
  8374. --------------------------------------------------------------------------
  8375. -- Algorithm  : Check case of reserve word, outputing necessary error
  8376. --                      messages.
  8377. --              Do a case on the reserve word, handling each appropriately
  8378. --------------------------------------------------------------------------
  8379.  
  8380. use TOKENIZER;
  8381. use STYLE_PARAMETERS;
  8382.  
  8383.   PHYSICAL_REPRESENTATION     : DYN.DYN_STRING;
  8384.  
  8385.   LOOK_AHEAD_TOKEN            : TOKENIZER.TOKEN;
  8386.  
  8387.   NAME_TOKEN                  : TOKENIZER.TOKEN;
  8388.  
  8389.   SEPARATOR_TYPE              : TOKENIZER.TOKEN_TYPE;
  8390.  
  8391.   LINE                        : TOKENIZER.LINE_NUM_RANGE;
  8392.   COLUMN                      : TOKENIZER.LINE_INDEX_RANGE;
  8393.  
  8394.   OLD_NEST_REC                : NESTING_RECORD; -- used for manipulation
  8395.                                                 -- of IN_BODY detection!
  8396.  
  8397.   PRAGMA_NAME : DYN.DYN_STRING;
  8398.  
  8399.   PREDEFINED_PRAGMA_MSG         : constant string :=
  8400.        "Transportability Note:  Pragma.";
  8401.   NON_STANDARD_PRAGMA_MSG       : constant string :=
  8402.        "Transportability Note:  Non-Standard Pragma!";
  8403.  
  8404.   ADDRESS_CLAUSE_MSG            : constant string :=
  8405.    "This may be a non-transportable statement (Address Clause).";
  8406.   REPRESENTATION_SPECS_MSG      : constant string :=
  8407.    "This may be a non-transportable statement (Representation Specification).";
  8408.  
  8409.   BAD_PACKAGE_MSG               : constant string :=
  8410.    "This package is on the list of packages to be warned against.";
  8411.  
  8412. function MATCH_PAREN(LEFT_PAREN : in TOKENIZER.TOKEN) RETURN TOKENIZER.TOKEN;
  8413. procedure PACKAGE_TOKEN_HANDLER(RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN);
  8414. procedure TASK_TOKEN_HANDLER(RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN);
  8415. procedure FUNCTION_PROCEDURE_TOKENS_HANDLER(
  8416.                 RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN);
  8417.  
  8418. function MATCH_PAREN(LEFT_PAREN : in TOKENIZER.TOKEN) RETURN TOKENIZER.TOKEN is
  8419.  
  8420.     NEXT_PAREN  : TOKENIZER.TOKEN := LEFT_PAREN;
  8421.  
  8422. begin
  8423.     NEXT_PAREN := NEXT_TOKEN(NEXT_PAREN);
  8424.     loop
  8425.         NEXT_PAREN := SEARCH_FORWARD_FOR_ONE_OF(NEXT_PAREN,
  8426.             TOKENIZER.RIGHT_PARENTHESIS, TOKENIZER.LEFT_PARENTHESIS);
  8427.         if TYPE_OF_TOKEN_IS(NEXT_PAREN) = TOKENIZER.LEFT_PARENTHESIS then
  8428.             NEXT_PAREN := MATCH_PAREN(NEXT_PAREN);
  8429.         else
  8430.             exit;
  8431.         end if;
  8432.     end loop;
  8433.     return NEXT_PAREN;
  8434. end MATCH_PAREN;
  8435.  
  8436. procedure PACKAGE_TOKEN_HANDLER(RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN) is
  8437.  
  8438.     LOOK_AHEAD_TOKEN : TOKENIZER.TOKEN;
  8439.  
  8440. begin
  8441. -- *******************************
  8442. -- When a PACKAGE token is encountered there are five
  8443. --      possibilities of context:
  8444. -- 1. PACKAGE specification
  8445. -- 2. PACKAGE BODY
  8446. -- 3. Rename of a package
  8447. -- 4. Instantiation of a generic package
  8448. -- 5. PACKAGE BODY <name> IS SEPARATE
  8449. -- *******************************
  8450.     LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8451.     if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = TOKENIZER.BODY_TOKEN then
  8452.         -- skip package name (an indentifier)
  8453.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8454.         -- skip IS token
  8455.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8456.         -- get next token after IS
  8457.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8458.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8459.             TOKENIZER.SEPARATE_TOKEN then
  8460.                 -- 2. Package body
  8461.                 CURRENT_STATUS.IN_GENERIC := FALSE;
  8462.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8463.                 -- else
  8464.                 -- 5. package body <name> is separate
  8465.         end if;
  8466.     else
  8467.         -- either
  8468.         -- 1. Package specification
  8469.         -- 3. Rename of a package
  8470.         -- 4. Instantiation of a generic package
  8471.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8472.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8473.             TOKENIZER.RENAMES_TOKEN then
  8474.             LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8475.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8476.                 TOKENIZER.NEW_TOKEN then
  8477.                 -- 1. Package specification
  8478.                 CURRENT_STATUS.IN_GENERIC := FALSE;
  8479.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8480.             -- else
  8481.             -- 4. Instantiation of a generic package
  8482.             end if;
  8483.         -- else
  8484.         -- 3. Rename of a package
  8485.         end if;
  8486.     end if;
  8487. end PACKAGE_TOKEN_HANDLER;
  8488.  
  8489. procedure TASK_TOKEN_HANDLER(RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN) is
  8490.  
  8491.     LOOK_AHEAD_TOKEN : TOKENIZER.TOKEN;
  8492.  
  8493. begin
  8494.     LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8495.     if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = TOKENIZER.BODY_TOKEN then
  8496.         --  TASK BODY task_simple_name IS ...
  8497.         --  or
  8498.         --  TASK BODY task_simple_name    IS SEPARATE ;
  8499.         -- skip the identifier
  8500.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8501.         -- skip the "IS"
  8502.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8503.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8504.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8505.             TOKENIZER.SEPARATE_TOKEN then
  8506.             ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8507.         end if;
  8508.     else
  8509.         --  TASK [TYPE] identifier
  8510.         --  or
  8511.         --  TASK [TYPE] identifier IS ...
  8512.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = TOKENIZER.TYPE_TOKEN
  8513.             then
  8514.             -- skip the TYPE token
  8515.             LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8516.         end if;
  8517.         -- skip the identifier
  8518.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8519.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8520.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = TOKENIZER.IS_TOKEN
  8521.             then
  8522.             ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8523.         end if;
  8524.     end if;
  8525. end TASK_TOKEN_HANDLER;
  8526.  
  8527. procedure FUNCTION_PROCEDURE_TOKENS_HANDLER(
  8528.                 RESERVE_WORD_TOKEN : in TOKENIZER.TOKEN) is
  8529.  
  8530.     LOOK_AHEAD_TOKEN : TOKENIZER.TOKEN;
  8531.  
  8532. begin
  8533.     begin
  8534.       LOOK_AHEAD_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8535.     exception
  8536.       when TOKENIZER.END_OF_TOKENS =>
  8537.           LOOK_AHEAD_TOKEN := RESERVE_WORD_TOKEN; -- not a WITH!
  8538.       when others =>
  8539.           raise;
  8540.     end;
  8541.     if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = WITH_TOKEN then
  8542.         --  WITH subprogram_specification [IS__name__or__<>] ;
  8543.         null;
  8544.     else
  8545.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8546.         -- skip the identifier
  8547.         LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8548.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = LEFT_PARENTHESIS then
  8549.             LOOK_AHEAD_TOKEN := MATCH_PAREN(LOOK_AHEAD_TOKEN);
  8550.             LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8551.         end if;
  8552.         -- for FUNCTION spec, pass by "return type_mark"
  8553.         if TOKENIZER.TYPE_OF_TOKEN_IS(RESERVE_WORD_TOKEN) = FUNCTION_TOKEN then
  8554.             LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8555.             LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8556.             while TOKENIZER.TYPE_OF_TOKEN_IS( LOOK_AHEAD_TOKEN ) =
  8557.                 TOKENIZER.PERIOD loop
  8558.                    -- This is an expanded name, i.e. name.name.name
  8559.                    LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8560.                    LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8561.             end loop;
  8562.         end if;
  8563.         if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = RENAMES_TOKEN then
  8564.             --  subprogram_specification  RENAMES subprogram_or_entry_name ;
  8565.             null;
  8566.         elsif TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = IS_TOKEN then
  8567.             LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8568.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) = NEW_TOKEN then
  8569.                 --  FUNCTION  designator IS
  8570.                 --      NEW generic_function_name [generic_actual_part] ;
  8571.                 -- or
  8572.                 --  PROCEDURE identifier IS
  8573.                 --      NEW generic_procedure_name [generic_actual_part] ;
  8574.                 null;
  8575.             elsif TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  8576.                 SEPARATE_TOKEN then
  8577.                 --  subprogram_specification IS SEPARATE ;
  8578.                 null;
  8579.             else
  8580.                 --  subprogram_body  ::=
  8581.                 --      subprogram_specification IS ...
  8582.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8583.                 CURRENT_STATUS.IN_GENERIC := FALSE;
  8584.             end if;
  8585.         else
  8586.         --  Subprogram specification
  8587.             null;
  8588.         end if;
  8589.     end if;
  8590. end FUNCTION_PROCEDURE_TOKENS_HANDLER;
  8591.  
  8592.  
  8593.  
  8594. begin -- RESERVE_WORD_ENCOUNTERED
  8595.  
  8596.     -- Check case of reserve word
  8597.     case CURRENT_STATUS.CASE_OF_RESERVED_WORDS is
  8598.         when STYLE_PARAMETERS.RESERVED_CASE_UPPER =>
  8599.             PHYSICAL_REPRESENTATION :=
  8600.                 TOKENIZER.EXTERNAL_REPRESENTATION(RESERVE_WORD_TOKEN);
  8601.             for I in 1..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8602.                 if (DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'A') or
  8603.                    (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'Z') then
  8604.                     REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,RESERVE_WORD_TOKEN,
  8605.                         "Reserve word " & DYN.STR(PHYSICAL_REPRESENTATION) &
  8606.                         " should be in upper case",
  8607.                         REPORT_GENERATOR.INVALID_CASE_FOR_A_KEYWORD);
  8608.                     STYLE_REPORT.INVALID_CASE_FOR_A_KEYWORD :=
  8609.                         STYLE_REPORT.INVALID_CASE_FOR_A_KEYWORD + 1;
  8610.                     exit;
  8611.                 end if;
  8612.             end loop;
  8613.         when STYLE_PARAMETERS.RESERVED_CASE_LOWER =>
  8614.             PHYSICAL_REPRESENTATION :=
  8615.                 TOKENIZER.EXTERNAL_REPRESENTATION(RESERVE_WORD_TOKEN);
  8616.             for I in 1..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8617.                 if (DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'a') or
  8618.                    (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'z') then
  8619.                     REPORT_GENERATOR.PUT_FLAW(FLAWS_FILE,RESERVE_WORD_TOKEN,
  8620.                         "Reserve word " & DYN.STR(PHYSICAL_REPRESENTATION) &
  8621.                         " should be in lower case",
  8622.                         REPORT_GENERATOR.INVALID_CASE_FOR_A_KEYWORD);
  8623.                     STYLE_REPORT.INVALID_CASE_FOR_A_KEYWORD :=
  8624.                         STYLE_REPORT.INVALID_CASE_FOR_A_KEYWORD + 1;
  8625.                     exit;
  8626.                 end if;
  8627.             end loop;
  8628.         when STYLE_PARAMETERS.RESERVED_CASE_CONSISTANT =>
  8629.         --  This will only be selected if this is the first reserve word
  8630.         --  encountered, in which case it will be used to decide which case
  8631.         --  to use.
  8632.             PHYSICAL_REPRESENTATION :=
  8633.                 TOKENIZER.EXTERNAL_REPRESENTATION(RESERVE_WORD_TOKEN);
  8634.             if (DYN.STR(PHYSICAL_REPRESENTATION)(1) >= 'a') and
  8635.                (DYN.STR(PHYSICAL_REPRESENTATION)(1) <= 'z') then
  8636.                 CURRENT_STATUS.CASE_OF_RESERVED_WORDS :=
  8637.                     STYLE_PARAMETERS.RESERVED_CASE_LOWER;
  8638.                 for I in 2..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8639.                     if (DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'a') or
  8640.                        (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'z') then
  8641.                         CURRENT_STATUS.CASE_OF_RESERVED_WORDS :=
  8642.                     STYLE_PARAMETERS.RESERVED_CASE_ANY;
  8643.                     exit;
  8644.                 end if;
  8645.             end loop;
  8646.             else
  8647.                 CURRENT_STATUS.CASE_OF_RESERVED_WORDS :=
  8648.                     STYLE_PARAMETERS.RESERVED_CASE_UPPER;
  8649.                 for I in 2..DYN.LENGTH(PHYSICAL_REPRESENTATION) loop
  8650.                     if (DYN.STR(PHYSICAL_REPRESENTATION)(I) < 'A') or
  8651.                        (DYN.STR(PHYSICAL_REPRESENTATION)(I) > 'Z') then
  8652.                         CURRENT_STATUS.CASE_OF_RESERVED_WORDS :=
  8653.                     STYLE_PARAMETERS.RESERVED_CASE_ANY;
  8654.                     exit;
  8655.                 end if;
  8656.             end loop;
  8657.             end if;
  8658.         when STYLE_PARAMETERS.RESERVED_CASE_ANY => null;
  8659.     end case;
  8660.     case TOKENIZER.TYPE_OF_TOKEN_IS(RESERVE_WORD_TOKEN) is
  8661.         when ABORT_TOKEN => null;
  8662.         when ABS_TOKEN => null;
  8663.         when ACCEPT_TOKEN => null;
  8664.         when ACCESS_TOKEN => null;
  8665.         when ALL_TOKEN => null;
  8666.         when AND_TOKEN => null;
  8667.         when ARRAY_TOKEN =>
  8668.             -- Array data structuring used!
  8669.             STYLE_REPORT.DATA_STRUCTURING_TYPES_NOT_USED(
  8670.                          REPORT_GENERATOR.ARRAY_TYPES):=false;
  8671.         when AT_TOKEN =>
  8672.             null;
  8673.         when BEGIN_TOKEN =>
  8674.             -- Either a block statement or a "body"
  8675.             if CURRENT_STATUS.IN_BODY then
  8676.                 ENTERING_BLOCK_STRUCTURE( RESERVE_WORD_TOKEN );
  8677.             else
  8678.                 CURRENT_STATUS.IN_BODY := TRUE;
  8679.                 -- Reset this block's IN_BODY status!
  8680.                 NEST_STACK.POP( OLD_NEST_REC, MISC_NEST_STACK );
  8681.                 OLD_NEST_REC.IN_BODY := TRUE;
  8682.                 NEST_STACK.PUSH( OLD_NEST_REC, MISC_NEST_STACK );
  8683.  
  8684.                 ENTERING_SUB_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8685.             end if;
  8686.         when BODY_TOKEN => null;
  8687.         when CASE_TOKEN =>
  8688.             -- Two possibilities
  8689.             -- 1. Start of an CASE statement
  8690.             -- 2. End of an CASE statement
  8691.             LOOK_AHEAD_TOKEN :=
  8692.                 PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8693.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8694.                 TOKENIZER.END_TOKEN) then
  8695.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8696.             end if;
  8697.         when CONSTANT_TOKEN => null;
  8698.         when DECLARE_TOKEN =>
  8699.             CURRENT_STATUS.IN_BODY := FALSE;
  8700.             ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8701.         when DELAY_TOKEN => null;
  8702.         when DELTA_TOKEN => null;
  8703.         when DIGITS_TOKEN => null;
  8704.         when DO_TOKEN =>
  8705.             -- Must accept statement block
  8706.             ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8707.         when ELSE_TOKEN =>
  8708.             -- Two possibilities
  8709.             -- 1. ELSE in an if or select
  8710.             -- 2. OR ELSE in an expression
  8711.             LOOK_AHEAD_TOKEN :=
  8712.                 PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8713.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8714.                 TOKENIZER.OR_TOKEN) then
  8715.                 null;
  8716.             else
  8717.                 STYLE_REPORT.OR_ELSES_USED := TRUE;
  8718.             end if;
  8719.         when ELSIF_TOKEN =>
  8720.                 STYLE_REPORT.ELSIFS_USED   := TRUE;
  8721.         when END_TOKEN =>
  8722.             EXITING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8723.         when ENTRY_TOKEN => null;
  8724.         when EXCEPTION_TOKEN => null;
  8725.             -- Two possibilities
  8726.             -- 1. Exception block
  8727.             -- 2. Exception declaration
  8728.             LOOK_AHEAD_TOKEN :=
  8729.                 PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8730.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8731.                 TOKENIZER.COLON) then
  8732.                 ENTERING_SUB_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8733.                 STYLE_REPORT.EXCEPTIONS_USED := TRUE;
  8734.             end if;
  8735.         when EXIT_TOKEN =>
  8736.             -- Handle exit in loop counting (only possibility)
  8737.             CURRENT_STATUS.EXITS_IN_LOOPS := CURRENT_STATUS.EXITS_IN_LOOPS + 1;
  8738.                 STYLE_REPORT.EXITS_USED    := TRUE;
  8739.         when FOR_TOKEN =>
  8740.             --  Three possibilities exist.
  8741.             --  1. FOR loop
  8742.             --  2. FOR attribute USE ...
  8743.             --  3. FOR name USE
  8744.             --  1 implies entering a block structure, but will be
  8745.             --    handled when the LOOP is encountered
  8746.             --  2 and 3 imply non-transportable things.
  8747.             --    To figure out which one we must look forward two
  8748.             --    tokens.
  8749.             LOOK_AHEAD_TOKEN :=
  8750.                 NEXT_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8751.             LOOK_AHEAD_TOKEN :=
  8752.                 NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8753.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  8754.                 TOKENIZER.USE_TOKEN) or
  8755.                (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  8756.                 TOKENIZER.TICK) then
  8757.                 -- This is a Representation-specification or address clause.
  8758.                 -- If the current case is:   "USE AT" then this is an
  8759.                 --  address clause, else Rep Spec.
  8760.                 LOOK_AHEAD_TOKEN :=
  8761.                     NEXT_NON_TRIVIAL_TOKEN(LOOK_AHEAD_TOKEN);
  8762.                 if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  8763.                    TOKENIZER.AT_TOKEN then
  8764.                     -- Address Clauses
  8765.                     STYLE_REPORT.ADDRESS_CLAUSES :=
  8766.                         STYLE_REPORT.ADDRESS_CLAUSES + 1;
  8767.                     if not STYLE_PARAMETERS.ADDRESS_CLAUSE_ALLOWED then
  8768.                         REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  8769.                            RESERVE_WORD_TOKEN,ADDRESS_CLAUSE_MSG,
  8770.                            REPORT_GENERATOR.ADDRESS_CLAUSE_USED);
  8771.                     end if;
  8772.  
  8773.                 else
  8774.                     -- Representation Specifications
  8775.                     STYLE_REPORT.REPRESENTATION_SPECIFICATIONS :=
  8776.                         STYLE_REPORT.REPRESENTATION_SPECIFICATIONS + 1;
  8777.                     if not STYLE_PARAMETERS.REPRESENTATION_SPECS_ALLOWED then
  8778.                         REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  8779.                            RESERVE_WORD_TOKEN,REPRESENTATION_SPECS_MSG,
  8780.                            REPORT_GENERATOR.REPRESENTATION_SPECIFICATION_USED);
  8781.                     end if;
  8782.                 end if;
  8783.             end if;
  8784.  
  8785.         when FUNCTION_TOKEN =>
  8786.             FUNCTION_PROCEDURE_TOKENS_HANDLER(RESERVE_WORD_TOKEN);
  8787.         when GENERIC_TOKEN => ENTERING_SUB_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8788.                               CURRENT_STATUS.IN_GENERIC := TRUE;
  8789.         when GOTO_TOKEN => null;
  8790.         when IF_TOKEN => null;
  8791.             -- Two possibilities
  8792.             -- 1. Start of an IF statement - will be handled when
  8793.             --         the THEN is encountered
  8794.             -- 2. End of an IF statement - will have been handled on the
  8795.             --         END statement
  8796.         when IN_TOKEN =>
  8797.             LOOK_AHEAD_TOKEN :=
  8798.                 NEXT_NON_TRIVIAL_TOKEN  ( RESERVE_WORD_TOKEN);
  8799.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  8800.                 TOKENIZER.OUT_TOKEN then
  8801.                 STYLE_REPORT.IN_OUTS_USED := TRUE;
  8802.             else
  8803.                 STYLE_REPORT.INS_USED     := TRUE;
  8804.             end if;
  8805.             when IS_TOKEN => null;
  8806.         when LIMITED_TOKEN => null;
  8807.         when LOOP_TOKEN =>
  8808.             LOOK_AHEAD_TOKEN :=
  8809.                 PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8810.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8811.                 TOKENIZER.END_TOKEN) then
  8812.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8813.             end if;
  8814.         when MOD_TOKEN => null;
  8815.         when NEW_TOKEN => null;
  8816.         when NOT_TOKEN => null;
  8817.         when NULL_TOKEN => null;
  8818.         when OF_TOKEN => null;
  8819.         when OR_TOKEN =>
  8820.             null;
  8821.         when OTHERS_TOKEN => null;
  8822.         when OUT_TOKEN =>
  8823.             LOOK_AHEAD_TOKEN :=
  8824.                 PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8825.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8826.                 TOKENIZER.IN_TOKEN then
  8827.                 STYLE_REPORT.OUTS_USED   := TRUE;
  8828.             end if;
  8829.         when PACKAGE_TOKEN => PACKAGE_TOKEN_HANDLER(RESERVE_WORD_TOKEN);
  8830.         when PRAGMA_TOKEN => null;
  8831.             -- Handle PRAGMA checks
  8832.             LOOK_AHEAD_TOKEN :=
  8833.                 NEXT_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8834.             PRAGMA_NAME :=
  8835.                 TOKENIZER.EXTERNAL_REPRESENTATION( LOOK_AHEAD_TOKEN );
  8836.             if STYLE_PARAMETERS.IS_A_PREDEFINED_PRAGMA(PRAGMA_NAME) then
  8837.                 REPORT_GENERATOR.INSERT_INTO_LIST(
  8838.                         STYLE_REPORT.PRAGMAS_USED,      PRAGMA_NAME );
  8839.                 if STYLE_PARAMETERS.NOTE_PRAGMAS = STYLE_PARAMETERS.ALL_PRAGMAS
  8840.                     then
  8841.                      REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  8842.                             RESERVE_WORD_TOKEN, PREDEFINED_PRAGMA_MSG,
  8843.                             REPORT_GENERATOR.PRAGMA_USED);
  8844.                 end if;
  8845.             else
  8846.                 REPORT_GENERATOR.INSERT_INTO_LIST(
  8847.                       STYLE_REPORT.NON_STANDARD_PRAGMAS_USED,    PRAGMA_NAME );
  8848.                 if STYLE_PARAMETERS.NOTE_PRAGMAS/= STYLE_PARAMETERS.NONE
  8849.                            then
  8850.                      REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE,
  8851.                             RESERVE_WORD_TOKEN, NON_STANDARD_PRAGMA_MSG,
  8852.                             REPORT_GENERATOR.NON_STANDARD_PRAGMA_USED);
  8853.                 end if;
  8854.             end if;
  8855.  
  8856.         when PRIVATE_TOKEN =>
  8857.             STYLE_REPORT.PRIVATES_USED := TRUE;
  8858.             -- Either a type declaration or private part
  8859.             LOOK_AHEAD_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8860.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8861.                 TOKENIZER.IS_TOKEN) and
  8862.                (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8863.                 TOKENIZER.LIMITED_TOKEN) then
  8864.                 ENTERING_SUB_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8865.             end if;
  8866.         when PROCEDURE_TOKEN =>
  8867.             FUNCTION_PROCEDURE_TOKENS_HANDLER(RESERVE_WORD_TOKEN);
  8868.         when RAISE_TOKEN => null;
  8869.         when RANGE_TOKEN => null;
  8870.         when RECORD_TOKEN => null;
  8871.             -- Either entering or exiting record declaration
  8872.             LOOK_AHEAD_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8873.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8874.                 TOKENIZER.END_TOKEN) then
  8875.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8876.                 -- Record types are used!  This includes their use in
  8877.                 -- representation specifications.
  8878.                 STYLE_REPORT.DATA_STRUCTURING_TYPES_NOT_USED(
  8879.                            REPORT_GENERATOR.RECORD_TYPES) := false;
  8880.             end if;
  8881.         when REM_TOKEN => null;
  8882.         when RENAMES_TOKEN => null;
  8883.         when RETURN_TOKEN => null;
  8884.         when REVERSE_TOKEN => null;
  8885.         when SELECT_TOKEN => null;
  8886.             -- Either entering or exiting select statement
  8887.             LOOK_AHEAD_TOKEN :=
  8888.                 PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8889.             if (TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8890.                 TOKENIZER.END_TOKEN) then
  8891.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8892.             end if;
  8893.         when SEPARATE_TOKEN => null;
  8894.         when SUBTYPE_TOKEN => null;
  8895.         when TASK_TOKEN =>
  8896.             LOOK_AHEAD_TOKEN := SEARCH_FORWARD_FOR_ONE_OF( RESERVE_WORD_TOKEN,
  8897.                                 TOKENIZER.IS_TOKEN,     -- means a block
  8898.                                 TOKENIZER.SEMICOLON);   -- just spec.
  8899.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  8900.                 TOKENIZER.IS_TOKEN then
  8901.                 ENTERING_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8902.             end if;
  8903.         when TERMINATE_TOKEN => null;
  8904.         when THEN_TOKEN => null;
  8905.             -- Three possibilities
  8906.             -- 1. AND THEN
  8907.             -- 2. IF <condition> THEN
  8908.             -- 3. ELSIF <condition> THEN
  8909.             -- If 1 then just count it
  8910.             -- If 2 then entering block structure
  8911.             -- If 3 then entering sub block structure
  8912.             --
  8913.             -- check for AND THEN
  8914.             LOOK_AHEAD_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN(RESERVE_WORD_TOKEN);
  8915.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) /=
  8916.                 TOKENIZER.AND_TOKEN then
  8917.                 -- this is either if..then or elsif..then
  8918.                 LOOK_AHEAD_TOKEN := SEARCH_BACKWARD_FOR_ONE_OF(
  8919.                                       RESERVE_WORD_TOKEN,
  8920.                                       TOKENIZER.IF_TOKEN,
  8921.                                       TOKENIZER.ELSIF_TOKEN );
  8922.                 if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN) =
  8923.                     TOKENIZER.IF_TOKEN then
  8924.                         ENTERING_BLOCK_STRUCTURE( RESERVE_WORD_TOKEN );
  8925.                 else
  8926.                         ENTERING_SUB_BLOCK_STRUCTURE( RESERVE_WORD_TOKEN );
  8927.                 end if;
  8928.             else
  8929.                 STYLE_REPORT.AND_THENS_USED := TRUE;
  8930.             end if;
  8931.         when TYPE_TOKEN => TYPE_DECLARATION(RESERVE_WORD_TOKEN);
  8932.         when USE_TOKEN =>
  8933.             null;
  8934.         when WHEN_TOKEN =>
  8935.             -- Possibilities
  8936.             -- 1. Variant record
  8937.             --  WHEN choice[|choice] =>
  8938.             -- 2. Case statement
  8939.             --  same as 1
  8940.             -- 3. Exception handler
  8941.             --  same as 1
  8942.             -- 4. Guarded select
  8943.             --  same as 1
  8944.             -- 5. EXIT [loop_name] WHEN
  8945.             --  EXIT loop_name WHEN-condition
  8946.             -- #1-4 are subblocks.  Distinguished in that they should NOT
  8947.             -- have an identifier before  the WHEN
  8948.             LOOK_AHEAD_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN( RESERVE_WORD_TOKEN);
  8949.             if TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN)
  8950.                /= TOKENIZER.IDENTIFIER then
  8951.                ENTERING_SUB_BLOCK_STRUCTURE(RESERVE_WORD_TOKEN);
  8952.                TOKENIZER.TOKEN_POSITION( RESERVE_WORD_TOKEN, LINE, COLUMN );
  8953.                --  The elements of the 'WHEN' clause must be indented
  8954.                --  further than the WHEN
  8955.                CURRENT_STATUS.CURRENT_INDENT := COLUMN;
  8956.             end if;
  8957.         when WHILE_TOKEN => null;
  8958.         when WITH_TOKEN => null;
  8959.             -- Possibilities
  8960.             -- 1. WITH package[,package|procedure]
  8961.             -- 2. WITH subprogram spec
  8962.             --          (generic parameter declaration)
  8963.             -- If this is withing packages then it is:
  8964.             -- with name [,name];
  8965.             NAME_TOKEN := NEXT_NON_TRIVIAL_TOKEN( RESERVE_WORD_TOKEN );
  8966.             LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN( NAME_TOKEN );
  8967.             SEPARATOR_TYPE   := TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN);
  8968.  
  8969.             while SEPARATOR_TYPE = TOKENIZER.COMMA or
  8970.                   SEPARATOR_TYPE = TOKENIZER.SEMICOLON loop
  8971.                -- Check package name
  8972.                if STYLE_PARAMETERS.IS_A_PROSCRIBED_PACKAGE(
  8973.                         TOKENIZER.EXTERNAL_REPRESENTATION( NAME_TOKEN ) ) then
  8974.                      REPORT_GENERATOR.INSERT_INTO_LIST(
  8975.                         STYLE_REPORT.PACKAGES_PROCEDURES_WITHED,
  8976.                         TOKENIZER.EXTERNAL_REPRESENTATION( NAME_TOKEN ));
  8977.                      -- Add an error class for 'withed packages'
  8978.                      REPORT_GENERATOR.PUT_FLAW( FLAWS_FILE, RESERVE_WORD_TOKEN,
  8979.                         BAD_PACKAGE_MSG, REPORT_GENERATOR.OTHER);
  8980.                end if;
  8981.                exit when SEPARATOR_TYPE = TOKENIZER.SEMICOLON;
  8982.                NAME_TOKEN := NEXT_NON_TRIVIAL_TOKEN( RESERVE_WORD_TOKEN );
  8983.                LOOK_AHEAD_TOKEN := NEXT_NON_TRIVIAL_TOKEN( NAME_TOKEN );
  8984.                SEPARATOR_TYPE := TOKENIZER.TYPE_OF_TOKEN_IS(LOOK_AHEAD_TOKEN);
  8985.             end loop;
  8986.         when XOR_TOKEN =>
  8987.             STYLE_REPORT.XORS_USED := TRUE;
  8988.         when others => null;
  8989.     end case;
  8990.     exception
  8991.         when others =>
  8992.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  8993.             TEXT_IO.PUT_LINE(" in RESERVE_WORD_ENCOUNTERED");
  8994.             raise;
  8995. end RESERVE_WORD_ENCOUNTERED;
  8996. ::::::::::
  8997. srch_backward.ada
  8998. ::::::::::
  8999. separate( STYLE_CHECKER )
  9000.  
  9001. function SEARCH_BACKWARD ( START_TOKEN : TOKENIZER.TOKEN;
  9002.                           GOAL_TYPE   : TOKENIZER.TOKEN_TYPE ) return
  9003.                               TOKENIZER.TOKEN is
  9004. --------------------------------------------------------------------------
  9005. -- Abstract   : This searches backward until it finds a given token type
  9006. --              If the beginning of the list is found, the first token is
  9007. --              returned as a 'failed' signal.
  9008. --------------------------------------------------------------------------
  9009. -- Parameters : START_TOKEN - Where to start searching from
  9010. --              GOAL_TYPE   - Type to look for
  9011. --------------------------------------------------------------------------
  9012. use TOKENIZER;
  9013.  
  9014.   CURRENT_TOKEN : TOKENIZER.TOKEN;
  9015. begin
  9016.    CURRENT_TOKEN := TOKENIZER.PREVIOUS_TOKEN( START_TOKEN );
  9017.    while TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE loop
  9018.       CURRENT_TOKEN := TOKENIZER.PREVIOUS_TOKEN( CURRENT_TOKEN );
  9019.    end loop;
  9020.    return CURRENT_TOKEN;
  9021. exception
  9022.    when TOKENIZER.END_OF_TOKENS =>        -- and first-token call?
  9023.       return TOKENIZER.FIRST_TOKEN;
  9024.  
  9025.    when others =>
  9026.       TEXT_IO.NEW_LINE;
  9027.       TEXT_IO.PUT("Inside SEARCH_BACKWARD -- exception:" );
  9028.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  9029. end SEARCH_BACKWARD;
  9030. ::::::::::
  9031. srch_back_one_of.ada
  9032. ::::::::::
  9033. separate(STYLE_CHECKER)
  9034.  
  9035. function SEARCH_BACKWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  9036.                           GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  9037.                           GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE )
  9038.                                              return TOKENIZER.TOKEN is
  9039. use TOKENIZER;
  9040. --------------------------------------------------------------------------
  9041. -- Abstract   : This searches backward until it finds one of the token types
  9042. --              If the beginning of the list is found, the first token is
  9043. --              returned as a 'failed' signal.
  9044. --------------------------------------------------------------------------
  9045. -- Parameters : START_TOKEN   - where to start the search
  9046. --              GOAL_TYPE1    - what to look for
  9047. --              GOAL_TYPE2    - what else to look for
  9048. --------------------------------------------------------------------------
  9049.   CURRENT_TOKEN : TOKENIZER.TOKEN;
  9050.   SOURCE_LINE   : DYN.DYN_STRING;
  9051.  
  9052. begin
  9053.    CURRENT_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN( START_TOKEN );
  9054.    while (TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE1) and
  9055.          (TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE2) loop
  9056.      CURRENT_TOKEN := PREVIOUS_NON_TRIVIAL_TOKEN( CURRENT_TOKEN );
  9057.    end loop;
  9058.    return CURRENT_TOKEN;
  9059. exception
  9060.  
  9061.    when TOKENIZER.END_OF_TOKENS =>
  9062.       return TOKENIZER.FIRST_TOKEN;
  9063.  
  9064.    when others =>
  9065.       TEXT_IO.NEW_LINE;
  9066.       TEXT_IO.PUT("Inside SEARCH_BACKWARD_FOR_ONE_OF -- exception:" );
  9067.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  9068.       TEXT_IO.PUT_LINE("While in line:");
  9069.       TOKENIZER.LINE_CONTAINING_TOKEN( START_TOKEN, SOURCE_LINE );
  9070.       TEXT_IO.PUT_LINE( DYN.STR( SOURCE_LINE ) );
  9071. end SEARCH_BACKWARD_FOR_ONE_OF;
  9072. ::::::::::
  9073. srch_forward.ada
  9074. ::::::::::
  9075. separate( STYLE_CHECKER )
  9076.  
  9077. function SEARCH_FORWARD ( START_TOKEN : TOKENIZER.TOKEN;
  9078.                           GOAL_TYPE   : TOKENIZER.TOKEN_TYPE ) return
  9079.                               TOKENIZER.TOKEN is
  9080. --------------------------------------------------------------------------
  9081. -- Abstract   : This searches until it finds a given token type
  9082. --              If the END_OF_FILE token is found, it is returned as
  9083. --              a 'fail' signal.
  9084. --------------------------------------------------------------------------
  9085. -- Parameters : START_TOKEN - where to start the search
  9086. --              GOAL_TYPE   - what to look for
  9087. --------------------------------------------------------------------------
  9088. use TOKENIZER;
  9089.  
  9090.   CURRENT_TOKEN : TOKENIZER.TOKEN;
  9091. begin
  9092. -- CURRENT_TOKEN := START_TOKEN; -- start the search with NEXT TOKEN!
  9093.    CURRENT_TOKEN := TOKENIZER.NEXT_TOKEN( START_TOKEN );
  9094.    while TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE loop
  9095.       if TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) = TOKENIZER.END_OF_FILE then
  9096.          exit;  -- just return this token as a 'failed' signal.
  9097.       end if;
  9098.       CURRENT_TOKEN := TOKENIZER.NEXT_TOKEN( CURRENT_TOKEN );
  9099.    end loop;
  9100.    return CURRENT_TOKEN;
  9101. exception
  9102.    when others =>
  9103.       TEXT_IO.NEW_LINE;
  9104.       TEXT_IO.PUT("Inside SEARCH_FORWARD -- exception:" );
  9105.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  9106. end SEARCH_FORWARD;
  9107. ::::::::::
  9108. srch_fore_one_of.ada
  9109. ::::::::::
  9110. separate( STYLE_CHECKER )
  9111.  
  9112. function SEARCH_FORWARD_FOR_ONE_OF ( START_TOKEN : TOKENIZER.TOKEN;
  9113.                           GOAL_TYPE1   : TOKENIZER.TOKEN_TYPE;
  9114.                           GOAL_TYPE2   : TOKENIZER.TOKEN_TYPE )
  9115.                                              return TOKENIZER.TOKEN is
  9116. use TOKENIZER;
  9117. --------------------------------------------------------------------------
  9118. -- Abstract   : This searches FORWARD until it finds one of the token types
  9119. --              If the end of the list is found, the END_OF_FILE token is
  9120. --              returned as a 'failed' signal.
  9121. --------------------------------------------------------------------------
  9122. -- Parameters : START_TOKEN - where to start the search
  9123. --              GOAL_TYPE1  - what to look for
  9124. --              GOAL_TYPE2  - what else to look for
  9125. --------------------------------------------------------------------------
  9126.   CURRENT_TOKEN : TOKENIZER.TOKEN;
  9127.   SOURCE_LINE   : DYN.DYN_STRING;
  9128.  
  9129. begin
  9130.    CURRENT_TOKEN := NEXT_NON_TRIVIAL_TOKEN( START_TOKEN );
  9131.    while (TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE1) and
  9132.          (TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) /= GOAL_TYPE2) loop
  9133.      if TOKENIZER.TYPE_OF_TOKEN_IS(CURRENT_TOKEN) = END_OF_FILE then
  9134.         exit;  -- just return this token as a 'failed' signal.
  9135.      end if;
  9136.      CURRENT_TOKEN := NEXT_NON_TRIVIAL_TOKEN( CURRENT_TOKEN );
  9137.    end loop;
  9138.    return CURRENT_TOKEN;
  9139. exception
  9140.    when others =>
  9141.       TEXT_IO.NEW_LINE;
  9142.       TEXT_IO.PUT("Inside SEARCH_FORWARD -- exception:" );
  9143.       TEXT_IO.PUT_LINE(CURRENT_EXCEPTION.NAME);
  9144.       TEXT_IO.PUT_LINE("While in line:");
  9145.       TOKENIZER.LINE_CONTAINING_TOKEN( START_TOKEN, SOURCE_LINE );
  9146.       TEXT_IO.PUT( DYN.STR( SOURCE_LINE ) );
  9147. end SEARCH_FORWARD_FOR_ONE_OF;
  9148. ::::::::::
  9149. type_declaration.ada
  9150. ::::::::::
  9151. separate (STYLE_CHECKER)
  9152.  
  9153. procedure TYPE_DECLARATION(FROM_THIS_TOKEN : in TOKENIZER.TOKEN) is
  9154.  
  9155. procedure CHECK_FOR_ENUMERATION( AT_THIS_TOKEN : in TOKENIZER.TOKEN ) is
  9156. -- ABSTRACT:  Check whether this TYPE definition is an enumeration type.
  9157. -- PARAMETERS: AT_THIS_TOKEN is pointing to the TYPE_TOKEN for the
  9158. --      type we are going to check.
  9159. -- ALGORITHM:
  9160. --      The relavent cases are:
  9161. --              TYPE name [Discriminant-part] ; -- incomplete type def
  9162. --              TASK TYPE name IS               -- TASK TYPE
  9163. --              TYPE name IS ( <> )             -- generic type
  9164. --              TYPE name [discriminant-part] IS ( enumeration
  9165. --                                              -- enumeration type!
  9166. --                                              -- I hope!
  9167. use TOKENIZER;
  9168.  
  9169. LOOKAHEAD  : TOKENIZER.TOKEN;
  9170. LOOKAROUND : TOKENIZER.TOKEN;
  9171.  
  9172. begin
  9173.     -- find the IS to eliminate the incomplete task type
  9174.     LOOKAHEAD := SEARCH_FORWARD_FOR_ONE_OF(AT_THIS_TOKEN,
  9175.                 TOKENIZER.SEMICOLON,  TOKENIZER.LEFT_PARENTHESIS );
  9176.  
  9177.     if TOKENIZER.TYPE_OF_TOKEN_IS( LOOKAHEAD ) = TOKENIZER.LEFT_PARENTHESIS then
  9178.        -- Inside here is NOT an incomplete type def.
  9179.        if TOKENIZER.TYPE_OF_TOKEN_IS(PREVIOUS_NON_TRIVIAL_TOKEN(
  9180.                AT_THIS_TOKEN ) ) /= TOKENIZER.TASK_TOKEN THEN
  9181.           -- Inside her if it is NOT a TASK TYPE
  9182.           if TOKENIZER.TYPE_OF_TOKEN_IS(
  9183.              NEXT_NON_TRIVIAL_TOKEN( LOOKAHEAD ) )
  9184.              /= TOKENIZER.BOX   then
  9185.                 -- Inside here if NOT a generic type.
  9186.  
  9187.                 -- This should be an enumeration type!
  9188.                 STYLE_REPORT.DATA_STRUCTURING_TYPES_NOT_USED(
  9189.                         REPORT_GENERATOR.ENUMERATION_TYPES) := false;
  9190.  
  9191.           end if;
  9192.        end if;
  9193.     end if;
  9194.  
  9195.     exception
  9196.         when others =>
  9197.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  9198.             TEXT_IO.PUT_LINE(" in CHECK_FOR_ENUMERATION");
  9199.             raise;
  9200. end CHECK_FOR_ENUMERATION;
  9201.  
  9202. begin
  9203.         CHECK_FOR_ENUMERATION( FROM_THIS_TOKEN );
  9204.     exception
  9205.         when others =>
  9206.             TEXT_IO.PUT(CURRENT_EXCEPTION.NAME);
  9207.             TEXT_IO.PUT_LINE(" in TYPE_DECLARATION");
  9208.             raise;
  9209. end TYPE_DECLARATION;
  9210. ::::::::::
  9211. style_help.ini
  9212. ::::::::::
  9213. 1 HELP
  9214. -- The text file used by the HELP_UTILITY Package is required to have a
  9215. -- particular format. If the file is not in this format, an exception will be
  9216. -- raised.  The following explains the required format.
  9217. --
  9218. -- COMMENTS: Comments may be embeded in the text file. All comments are ignored
  9219. -- when the file is read into memory. A text line is considered a comment if
  9220. -- the first and second characters of the line are minus signs ( -- ).
  9221. --
  9222. -- TOPICS: The first non-comment text line MUST begin with the digit 1 in
  9223. -- column one. This number is the topic level. In other words, text (as
  9224. -- defined below) cannot be found in the text file before a topic is found to
  9225. -- which the text can be associated. Topics are those subjects for which
  9226. -- information is being provided. A topic name may contain any printable
  9227. -- character except blanks.  Embedded blanks are NOT allowed in a topic name.
  9228. -- This will not be flagged as an error but the name will be truncated at
  9229. -- the first blank. All letters in the name must be capitals. It is not
  9230. -- required to have a space separating the topic level from the topic name.
  9231. -- Any line beginning with a digit will be considered a topic line.
  9232. --
  9233. -- SUBTOPICS: A topic may have subtopics. Subtopics are denoted by having a
  9234. -- level exactly one greater than the associated topic level. Subtopics
  9235. -- follow the same rules as topics in all other aspects. There is no
  9236. -- constraint (other than a lack of memory) on the number of subtopic levels.
  9237. --
  9238. -- TEXT: All text lines not beginning with two consecutive minus signs or a
  9239. -- digit will be considered text.
  9240. --
  9241. -- The text file is saved exactly as the user sees it (including blank lines)
  9242. -- with the follow exceptions:
  9243. --
  9244. --       o topic and subtopic names have leading blanks stripped off
  9245. --       o if the topic or subtopic name is longer than one half the screen
  9246. --         size, it may be truncated when a menu of information is output
  9247. --       o if the text line is longer than the screen size, the text line is
  9248. --         truncated before output
  9249. --       o the text file lines are assumed to be eighty characters maximum.
  9250. This is the Help Facility for the Style Checker. More information
  9251. on specific topics may be obtained by entering the leading portion
  9252. of the name of any of the topics.
  9253.  
  9254. To get the list of topics available at any time, enter a ? at
  9255. the prompt.
  9256.  
  9257. To list the information on all topics below the current topic, enter
  9258. a * at the prompt.
  9259.  
  9260. To exit the Help Facility, enter a <CR> for each level of information.
  9261.  
  9262. 2 INSTALLATION
  9263. The original STYLE_CHECKER program was written on a Data General MV-10000
  9264. using the Data General Ada Development Environment.  No features specific
  9265. to the ADE were used and moving the system to another computer should be
  9266. simple.
  9267.  
  9268. The command file invoking the tool may have to be rewritten, two or three
  9269. file names specific to the installation may have to be changed, and the
  9270. system will have to be compiled.
  9271.  
  9272. Moving the system should require no rewriting of the Ada source code (other
  9273. than changing three internal file names).
  9274.  
  9275. For more information on modifying the Style Checker, see the MAINTENANCE
  9276. section of HELP.
  9277.  
  9278. 3 COMPILATION
  9279. The Style-Checker consists of nine packages.  They are:
  9280.  
  9281. DYN              -- Dynamic strings
  9282. STACK_PACKAGE    -- Generic stacks
  9283. COMMAND_LINE     -- Get parameters from the command line
  9284. HELP_PACKAGE     -- Display Help Information
  9285. FILE_HANDLING    -- System dependencies & front-end file handling
  9286. TOKENIZER        -- Convert Ada to tokens
  9287. STYLE_PARAMETERS -- Deliver parameters defining the style
  9288. REPORT_GENERATOR -- Produce style outputs
  9289. STYLE_CHECKER    -- Main Procedure
  9290.  
  9291. Some of these packages contain both specifications and bodies.  Also, there
  9292. are 'separate' procedures for some of the packages.  Because of the
  9293. dependencies, the individual files must be compiled in specific order.
  9294.  
  9295. The order of compilation is defined in a file in the Style Checker
  9296. Source directory.  That file is named "COMPILE.CLI".
  9297.  
  9298. 3 SPECIFIC_FILE_NAMES
  9299. There are three hard-coded file names in the tool which may have to be
  9300. modified.  These three file name constants are all located in the
  9301. FILE_HANDLING package.  They may have to be modified to reflect where
  9302. the Style Checker is installed, or to conform to the host's file-naming
  9303. conventions.
  9304.  
  9305. COMMAND_LINE_FILE_NAME -- This file will contain the parameters from
  9306.   the command line which invokes the tool.  The default name given is
  9307.   COMMAND_LINE.TXT (on the MV-10000).  This file will be created in
  9308.   the users current directory as the tool is run.  SEE the HELP section
  9309.   on the COMMAND_FILE and on Style Checker OPERATION.
  9310.   This is defined in the FILE_HANDLING body, currently named:
  9311.   FILE_BODY.ADA
  9312.  
  9313. HELP_FILE_NAME -- This file points to the HELP file.  This file will
  9314.   be located in the Style Checker source directory.
  9315.   The current name is "STYLE_HELP.INI".
  9316.   This is defined in the FILE_HANDLING specifications, currently named:
  9317.   FILE_SPEC.ADA
  9318.  
  9319. STYLE_DICTIONARY_NAME -- This file points to the DICTIONARY file.
  9320.   Currently this feature IS NOT USED.  This constant exists for future
  9321.   expansion.
  9322.   The current name is "STYLE_DICTIONARY.INI".
  9323.   This is defined in the FILE_HANDLING specifications, currently named:
  9324.   FILE_SPEC.ADA
  9325.  
  9326. 3 COMMAND_FILE
  9327. A command procedure is used to invoke the Style Checker.  This is written in
  9328. the host's command language.  Its function is to process the parameters
  9329. on the command line and call the Style Checker.
  9330.  
  9331. The command line parameters are passed to the Style Checker by putting them
  9332. into a text file.  Each parameter becomes a single line in the file.  This
  9333. file's name is predefined and corresponds to the COMMAND_LINE_FILE_NAME
  9334. defined in the FILE_HANDLING package.
  9335.  
  9336. The command procedure supplied with the Style Checker is written for the
  9337. Data General command language.  This file is in the Style Checker's
  9338. source directory and the file is "STYLE.CLI".
  9339.  
  9340. The parameters on the command line are the files to be style-checked.  The
  9341. parameters are explained more in the OPERATION section of HELP
  9342.  
  9343. 2 OPERATION
  9344. The Style Checker is invoked by the command procedure and is given parameters
  9345. describing the input files.  On the Data General this looks like:
  9346.  
  9347. STYLE FILE1 FILE2 FILE3
  9348.  
  9349. More information on the format of the command line is below in
  9350. STYLE_CHECKER_COMMAND
  9351.  
  9352. The Style Checker will read in the set of input
  9353. files.  This input will be style-checked.  The results will be written out
  9354. as two files, a flaws file, listing individual stylistic errors, and a style
  9355. report, which summarizes the style of the document.
  9356.  
  9357. The output file names are derived from the name of the FIRST input file.
  9358.  
  9359. 3 STYLE_CHECKER_COMMAND
  9360. The command to invoke the Style Checker contains the phrase for the command
  9361. procedure (on the Data General this is "STYLE") and one or more file
  9362. descriptors.
  9363.  
  9364. The file descriptor is either a file name, or a file name preceeded by a
  9365. "@" character.
  9366.  
  9367. If it is a file name, that file contains the Ada source code to be style-
  9368. checked.
  9369.  
  9370. If the file name is preceeded by a "@", then this file is a list, containing
  9371. the names of other files to be style checked.  This is useful when the user
  9372. wishes to check a large number of files.  For example, if the file
  9373. "FILE_HANDLING.DIS" contains the following:
  9374. COMMAND_LINE.ADA
  9375. FILE_SPEC.ADA
  9376. FILE_BODY.ADA
  9377. <EOF>
  9378.  
  9379. then these three files could be style checked by the following command:
  9380.  
  9381. STYLE @FILE_HANDLING.DIS
  9382.  
  9383. These "list" files are ordinary text files.  They can contain nested references
  9384. to other "list" files.  This can be nested up to 10 levels deep.
  9385.  
  9386. An example of this can be seen as the following file:
  9387. @FILE_HANDLING.DIS
  9388. DYN.ADA
  9389. @TOKENIZER
  9390. HELP.ADA
  9391. STACK.ADA
  9392. @REPORT_GEN.DIS
  9393. @STYLE_PARAM.DIS
  9394. @STYLE_CHECKER.DIS
  9395. <EOF>
  9396.  
  9397. If the above were used as input to the Style Checker, it would check
  9398. the three files and the other files listed in the five "list" files.
  9399.  
  9400. 3 INPUT_FILES
  9401. The input to the Style Checker is a set of input files which are concatenated
  9402. together and treated as if they were one input file.
  9403.  
  9404. The input is expected to be syntactically correct Ada.  If the input is not
  9405. correct Ada, the Style Checker will in many cases be able to check the
  9406. input anyway, but this may cause erroneous results.
  9407.  
  9408. There are some cases where incorrect Ada input will cause the Style Checker
  9409. to malfunction.  A major example of this is the nesting of blocks.  If the
  9410. input program contains too many "END" statements, the Style Checker currently
  9411. is unable to recover and will usually fail, producing only a partial "flaws"
  9412. list and no "report" output.
  9413.  
  9414. Because of this, it is best to be sure the input is correct Ada before trying
  9415. to check its style.
  9416.  
  9417. 3 OUTPUT_FILES
  9418. The Style Checker produces two output files.  The names of these files are
  9419. derived from the first real input file (not from the "list" files).  The
  9420. file name extension is stripped from the input file name.  The extension
  9421. "FLW" is added to create the "flaws" file name.  The extension "STY" is
  9422. added to create the "report" file name.
  9423.  
  9424. EXAMPLE:  If the Style Checker were invoked by:
  9425.  
  9426. STYLE TEST1.ADA COPYFILE.ADA ANOTHER.ADA
  9427.  
  9428. then the output file names would be:
  9429. TEST1.FLW, and
  9430. TEST1.STY.
  9431.  
  9432. Examples of "flaws" and "report" files can be found in the Style Checker
  9433. Testing directory.  For each test file, there will be a "flaw" file and
  9434. a "report" file.
  9435.  
  9436.  
  9437. 4 FLAWS_FILE
  9438. The "flaws" file contains notices of individual style mistakes.  Each notice
  9439. includes the style "flaw" which was found, and a copy of the source line in
  9440. which the flaw was located.
  9441.  
  9442. Discussions of the individual flaws reported can be found under the discussion
  9443. of INDIVIDUAL_PARAMETERS in HELP.
  9444.  
  9445. OUTPUT DISCREPANCIES:
  9446.      Be aware that the output of flaws is generated when the flaw is discovered.
  9447. This may not be when the line is first parsed.  For example, the size of loops,
  9448. or procedures is not known until the end of the loop or procedure, so the
  9449. flaws file will contain output flaws from the middle of the loop, and then
  9450. later show the start of the loop and say that this loop is too large.
  9451.  
  9452. Statements which span lines will not be completely be printed when a flaw
  9453. is reported.  The Style Checker trys to print the line containing the erroneous
  9454. part of the statement, but it does not always succeed.
  9455.  
  9456. If one particular error occurs too many times, it would be repetitive to
  9457. continue listing that error.  Accordingly, there is a parameter,
  9458. "ERRORS_TO_LIST", which puts a limit on how many times an individual error
  9459. is output.  The default setting is 5.  This means that if the input contained
  9460. many indentation errors, only the first 5 would be noted in the flaws file.
  9461. The other indentation errors would still be included as part of the style
  9462. report file.
  9463.  
  9464. 4 REPORT_FILE
  9465. The "report" file contains a summary of the style problems encountered in
  9466. the source.  This is a combined summary for the total input.  If reports are
  9467. desired for individual files, they will have to be style-checked separately.
  9468.  
  9469. The style report indicates
  9470.   A. Counts of flaws
  9471.   B. Limits exceeded -- this is typically the average of some check
  9472.      mode over the entire input, such as average length of names.
  9473.   C. Notes of other style issues -- this may be notes that the input
  9474.      does not show use of some Ada feature such as enumeration types.
  9475.  
  9476. If the line is showing a style error, then the line is flagged by putting
  9477. a "*" before the line.  If the line contains minor problems, or
  9478. nothing is wrong, but the user might be able to improve, the line
  9479. is flagged with a "!".
  9480.  
  9481. The individual sections of the style report are in subsections below.
  9482. These describe the meaning of the information.  The actual results depend
  9483. on the definition of the style parameters.  For more information on the actual
  9484. style checked, see the HELP section on INDIVIDUAL_PARAMETERS.
  9485.  
  9486. 5 NAMING_CONVENTIONS
  9487. Example:
  9488. >-------------------------------------------------------------------------
  9489. > *   Invalid Case for an Object Identifier           133      Errors
  9490. > *   Invalid Case for a Keyword                        3      Errors
  9491. >     Name Segment Size (Separated         Desired     <5      Characters
  9492. >                 by Underscores)          Actual       4.1    Characters
  9493. >     Average Name Size                    Desired     >5      Characters
  9494. >                                          Actual      15.5    Characters
  9495. >-------------------------------------------------------------------------
  9496.  
  9497. This section deals with words.  The instances of names being typed in the
  9498. wrong case are shown.  Also shown is the average length of names,
  9499. and a measurement showing whether enough underscores are used.
  9500.  
  9501. See Help information on INDIVIDUAL_PARAMETERS for explanations of the
  9502. following:
  9503.  
  9504. SHORT_WORD     RESERVED_CASE  OBJECT_CASE    AVE_NAME_LEN
  9505. UNDERSCORES    UNDERSCORE_SIZE
  9506.  
  9507.  
  9508. 5 PHYSICAL_LAYOUT
  9509. >-------------------------------------------------------------------------
  9510. > *   Occurrences of More Than One Statement/Line      51      Errors
  9511. > *   Inconsistant Indentation                        596      Errors
  9512. > *   Missing Blank Lines to Set Off a Block          113      Errors
  9513. > *   Loops Without Names                              12
  9514. >-------------------------------------------------------------------------
  9515. This section relates to readability.  Most of these are self-explanatory.
  9516. Note that structures (packages, loops, etc.) may be required to have blank
  9517. lines surrounding them, and loops should have loop-names.  These are only
  9518. required when the given structure is larger than a limit defined in the style.
  9519.  
  9520. See Help information on INDIVIDUAL_PARAMETERS for explanations of the
  9521. following:
  9522.  
  9523. SMALL_STRUCTURE     STATEMENT_LINE      INDENT_TYPES        INDENT_COMMENTS
  9524. BLANK_LINES         LOOP_NAMES
  9525.  
  9526.  
  9527. 5 INFORMATION_HIDING
  9528. >-------------------------------------------------------------------------
  9529. >     Percent of Literals In Body          Desired   < 10.0%
  9530. > *                                        Actual      79.7%
  9531. >     Percent of Universal Types           Desired   < 40.0%
  9532. >                                          Actual      20.0%
  9533. > !   Data Structuring Types NOT Used
  9534. >                                          Array Types
  9535. >                                          Enumeration Types
  9536. >                                          Record Types
  9537. > !   No Attributes are Used
  9538. > !   Ada-Specific Features NOT used
  9539. >                                          AND THEN
  9540. >                                          OR ELSE
  9541. >                                          EXITS
  9542. >                                          XOR
  9543. >                                          ELSIF
  9544. >                                          EXCEPTION
  9545. >                                          IN parameters
  9546. >                                          OUT parameters
  9547. >                                          IN OUT parameters
  9548. >-------------------------------------------------------------------------
  9549. This measures the number of literals (both string and numeric) in the body
  9550. with respect to those in the declaration sections.  Also the percentage of
  9551. universal type (integer, etc.) compared to other type is measured.  The use
  9552. of data structuring types and Ada-specific features is also detected.  The
  9553. next line indicates that the input uses no attributes.
  9554.  
  9555. The "!" shows that the user might profit by learning more about these features.
  9556.  
  9557. See Help information on INDIVIDUAL_PARAMETERS for explanations on the
  9558. following:
  9559.  
  9560. PERCENT_LITERALS    PERCENT_UNIVERSALS       ATTRIBUTE_CHECK
  9561. DATA_STRUCTURES
  9562.  
  9563. 5 MODULARITY
  9564. >-------------------------------------------------------------------------
  9565. >     Average Number of Parameters         Range     1..8      Parameters
  9566. > *     Instances of parameters below minimum           6
  9567. >       Instances of parameters above maximum           0
  9568. >     Average Subprogram Size              Range  10..200      Statements
  9569. > *     Instances of size below minimum                 6
  9570. > *     Instances of size above maximum                 2
  9571. >     Loops with too many exit statements               0      Instances
  9572. >     Control Structure Nesting            Maximum      8
  9573. >                                          Exceeded     0      Instances
  9574. >     Package Nesting                      Maximum      2
  9575. >                                          Exceeded     0      Instances
  9576. >     Subprogram Nesting                   Maximum      4
  9577. >                                          Exceeded     0      Instances
  9578. >-------------------------------------------------------------------------
  9579.  
  9580. Size and nesting are used as measurements of modularity.  There are limits
  9581. on the size of subprograms, and on how many parameters they have.
  9582. There is a limit on the number of exits a loop may have.  The last six lines
  9583. show the nesting of the input.
  9584.  
  9585. See Help information on INDIVIDUAL_PARAMETERS for explanations on
  9586. the following :
  9587.  
  9588. SUBPROGRAM_SIZE     SUBPROGRAM_PARAMETERS    NUMBER_OF_LOOP_EXITS
  9589. CONTROL_NESTING     PACKAGE_NESTING          SUBPROGRAM_NESTING
  9590.  
  9591. 5 COMMENT_USAGE
  9592. >-------------------------------------------------------------------------
  9593. >     Number of Comments                              606      Comments
  9594. >     Average Comment Size                 Desired    >15      Characters
  9595. >                                          Actual      38.8    Characters
  9596. >-------------------------------------------------------------------------
  9597. The comment size is recorded so that the program cannot be fooled by
  9598. simply adding a large number of blank comments.
  9599.  
  9600. See Help information on INDIVIDUAL_PARAMETERS for COMMENT_SIZE explanation.
  9601.  
  9602. 5 TRANSPORTABILITY
  9603. >-------------------------------------------------------------------------
  9604. > *   Number of Lines Exceeding Line Length            69
  9605. >     Address Clauses                                   0
  9606. >     Representation Specifications                     0
  9607. >     PRAGMA'S used:
  9608. >                                          INLINE
  9609. >     Non-Standard PRAGMA's Used
  9610. >                                          MAIN
  9611. >     Packages/Procedures WITHed
  9612. >                                          CURRENT_EXCEPTION
  9613. >-------------------------------------------------------------------------
  9614.  
  9615. This notes features which may be untransportable.  "Pragma's used" lists
  9616. pragmas defined in the LRM.  "Non-Standard pragma's" lists other pragmas.
  9617. "Packages withed" lists any packages in the input which are defined in the
  9618. style as "proscribed" packages.  This typically includes non-transportable
  9619. packages such as SYSTEM, UNCHECKED_CONVERSION, etc.
  9620. This section might also show the presence of any characters which are not
  9621. in the allowable set defined in the style.  The final item is a notice
  9622. describing the use of Ada features which are not available in other languages.
  9623. This is intended to provide information for the user to see what could be
  9624. learned to improve their programs.
  9625.  
  9626. See Help information on INDIVIDUAL_PARAMETERS for explanations on the
  9627. following:
  9628.  
  9629. LINE_SIZE           REPRESENTATION_SPECS     ADDRESS_CLAUSE
  9630. PRAGMAS             PREDEFINED_PRAGMA        PROSCRIBED_PACKAGE
  9631. CHARACTER_SET
  9632.  
  9633.  
  9634. 5 KEYWORD_USAGE
  9635. >Used Keyword    Allowed         Restriction     Occurrences     Percentage
  9636. >-------------------------------------------------------------------------
  9637. >     AT        yes             0.0%            0               0.0%
  9638. >     DO        yes             0.0%            0               0.0%
  9639. >     IF        yes             0.0%          258              13.5%
  9640. >     IN        yes             0.0%           74               3.9%
  9641. .
  9642. .
  9643. .
  9644. >     GOTO      yes             5.0%            0               0.0%
  9645. >     LOOP      yes             0.0%           60               3.1%
  9646. >--------------------------------------------------------------------------
  9647.  
  9648. This optional list shows the Ada reserved words, whether the style allows
  9649. their use, and how often they were used in the input.
  9650.  
  9651. See Help on INDIVIDUAL_PARAMETERS for KEYWORD_PARAMETERS explanation.
  9652.  
  9653.  
  9654. 2 INDIVIDUAL_PARAMETERS
  9655. The parameters defining the limits of the Ada style are  defined
  9656. in the body of the FILE_HANDLING package.  In that body the default values
  9657. are specified as defaults for the individual parameter variables.  There
  9658. is also a procedure SET_STYLE_PARAMETERS which sets the actual values for
  9659. the style.
  9660.  
  9661. It is expected that any local changes to the style parameters will be done in
  9662. the SET_STYLE_PARAMETERS procedure, so that the original defaults remain
  9663. unchanged.
  9664.  
  9665.  
  9666. 3 ERRORS_TO_LIST
  9667. To  avoid  redundantly  repeating  instances of detected errors,
  9668. the ' errors-to-list'  parameter  restricts  the number of times
  9669. any  one  error  is  listed.  This  means, for example, only the
  9670. first 5 times the user forgot to use loop-names would be listed.
  9671. Other  occurences  of  each  individual error  would be counted,
  9672. and the total instances of the error would be noted on the style
  9673. summary.
  9674.  
  9675. 3 OUTPUT_KEYWORD_LIST
  9676. To shorten the output, the Style Checker may be set to not  print
  9677. the  complete  summary of reserved words used.   The options are:
  9678.      ALL_KEYS       Print all keywords
  9679.      USED           Print only those keywords which are used
  9680.      NOT_USED       Print only those keywords which are not used
  9681.      ERRORS         Print those keywords whose usage is in error
  9682.      NONE           Do not print keywords
  9683.  
  9684. 3 SHORT_PROGRAM
  9685. The  Short-Program  parameter  measures  the size of subprograms
  9686. which  are  too  small  to  be  considered  significant for some
  9687. measures.  The  parameter  is an integer, N, where programs less
  9688. than N statements are 'short'.
  9689.  
  9690. Short  programs  may  not  contain enough  information  to  make
  9691. valid  judgements  on  whether  'restricted'  reserved words are
  9692. used  too  often.  These  measurements  will still be made,  but
  9693. the user should be aware that they not be significant.
  9694.  
  9695. 3 SHORT_WORD
  9696. The  Short-Word  parameter  defines  the size, in characters, of
  9697. 'small'  words.  Words this small or smaller are detected as too
  9698. small  to   effectively  identify  the   object's  contents.  In
  9699. addition,  words this short will not be checked for the presence
  9700. of underscores,  or  checked for abbreviations.
  9701.  
  9702. 3 SHORT_STRUCTURE
  9703. Some sections of  code are too short to be  reasonably  checked.
  9704. For  example,  loop names may be required on control structures,
  9705. but  it  is  not  reasonable to require them on very short loops
  9706. (such   as   a   1-statement   loop).   Anything   which     has
  9707. 'short-structure'  statements  or less is small and doesn't have
  9708. to be checked for loop-names, blank  lines around the loop, etc.
  9709.  
  9710. 3 RESERVED_CASE
  9711. Reserved-Case is an  enumeration object  indicating  the defined
  9712. style of  presenting  reserved  words as all capitals, all lower
  9713. case, or mixed cases.   The values are:
  9714.  
  9715.       *  ReservedCaseUpper:  Reserved words  must  be  upper
  9716.          case.
  9717.  
  9718.       *  ReservedCaseLower:  Reserved words  must  be  lower
  9719.          case.
  9720.  
  9721.       *  ReservedCaseConsistant:   Reserved  word  case   is
  9722.          determined  by  the case of the FIRST reserved word
  9723.          encountered.  All subsequent words must be the same
  9724.          case.
  9725.  
  9726.       *  ReservedCaseAny:  Reserved words  do  not  have  to
  9727.          follow any convention.
  9728.  
  9729. 3 OBJECT_CASE
  9730. Object-Case is  an  enumeration  object indicating  the  defined
  9731. style  of  presenting names as all capitals,  all lower case, or
  9732. mixed cases.  The values are:
  9733.  
  9734.       *  NameCaseUpper:  Names must be upper case.
  9735.  
  9736.       *  NameCaseLower:  Names must be lower case.
  9737.  
  9738.       *  NameCaseFirstCapitalized:   The  first  letter   of
  9739.          names  must  be  capitalized.  The name may contain
  9740.          other capitalized letters such as when  a  name  is
  9741.          the    concatenation   of   several   words   like:
  9742.          LinesOfCode or GeometricMean.
  9743.  
  9744.       *  NameCaseConsistant:  Name case is determined by the
  9745.          case of the FIRST name encountered.  All subsequent
  9746.          words must be the same case.
  9747.  
  9748.       *  NameCaseAny:  Names  do  not  have  to  follow  any
  9749.          convention.
  9750.  
  9751. 3 AVE_NAME_LEN
  9752. This parameter is a  positive  integer used to judge whether the
  9753. user is replying on too many small names.  If the average length
  9754. of names over the whole program is less than this value,  then a
  9755. style  flaw  has occured.  The user is told he is using too many
  9756. short names.
  9757.  
  9758. 3 UNDERSCORES
  9759. This is a flag indicating  whether underscores should be checked
  9760. for.  On some computers or for some  systems underscores may not
  9761. be a desirable feature.  If the  flag is TRUE,  the presence and
  9762. frequency of underscores will be  checked  as  detailed  in  the
  9763. HELP on underscore-size.  If the flag is FALSE, underscores will
  9764. be ignored.   Note that FALSE does not mean that underscores are
  9765. incorrect.
  9766.  
  9767. 3 UNDERSCORE_SIZE
  9768. If underscores are required, the style  checker  will  check the
  9769. average number of characters not  separated  by underscores in a
  9770. program.    If   the   resultant   average   is   greater   then
  9771. underscore-size, the user has too few  underscores in his names.
  9772.  
  9773. The specific method of checking this is as follows:
  9774.  
  9775.      A.  If the  name  is  short  (less  than  or  equal  to
  9776.          'small-word' characters) it is ignored.
  9777.  
  9778.      B.  Count the characters in each segment of  the  name,
  9779.          where segments are separated by underscores.
  9780.  
  9781.      C.  Average these counts over the whole program.
  9782.  
  9783.      D.  If   the   program   average   is   greater    than
  9784.          underscore-size, an error report is made.
  9785.  
  9786. 3 VOWEL_FREQUENCY
  9787. While  abbreviations  save typing time, it is easy to abbreviate
  9788. too much, and for maintenance programmers,  who  are  not at all
  9789. familiar with a program, any abbreviations  are  confusing.  The
  9790. heuristic used to try to detect abbreviations is the  percentage
  9791. of  vowels   WRT consonants in  the  names.   Since  the  common
  9792. forms  of abbreviation  involve striping out the vowels, if  the
  9793. names have  too  few   vowels,   the   programmer   is  probably
  9794. abbreviating.
  9795.  
  9796. The program calculates the percentage of vowels versus the total
  9797. number of letters in the word.  These percentages  are  averaged
  9798. over the entire program and if  this  percentage  is  under  the
  9799. 'Vowel-Frequency'  parameter,  a  style  flaw is noted.
  9800.  
  9801. 3 SPELLING_REQUIRED
  9802. This function is currently only existant as a stub.
  9803. It is eventually intended to check individual  name  segments  of
  9804. words  against  a project dictionary to see if the words used are
  9805. allowable.
  9806.  
  9807. 3 INDENT_TYPES
  9808. This  is  a  flag  indicating whether  to check  for  consistant
  9809. indenting in the declaration portions of a program. If TRUE, the
  9810. style  checker  will  note  inconsistant   indentation   in  the
  9811. declarations  as a style flaw.
  9812.  
  9813. 3 INDENT_COMMENTS
  9814. This  is  a  flag indicating  whether to  check  for  consistant
  9815. indenting  in the comments which follow  statements  on the same
  9816. line.
  9817.  
  9818.      NULL;               -- This is a trailing comment
  9819.  
  9820. If  TRUE,  the  style checker will note inconsistant indentation
  9821. in the trailing comments as a style flaw.
  9822.  
  9823. 3 BLANK_LINES
  9824. To physically separate control structure  on  the  listing,  the
  9825. style  may  require  blank lines to  be  placed  around  control
  9826. structures.  If  this  parameter is TRUE, the absence  of  blank
  9827. lines  around  control structures will be noted as a style flaw.
  9828. For example:
  9829.  
  9830.      NULL;                            -- Previous statement
  9831.  
  9832.      LOOP                             -- Blank line before and after
  9833.         NULL;                         -- this loop
  9834.      END LOOP;
  9835.  
  9836.      NULL;                            -- Next statement(s)
  9837.  
  9838. 3 LOOP_NAMES
  9839. To help locate the beginning and end of  structures,  the  style
  9840. may require loop names at the start  and  end.  These  names are
  9841. required if the parameter is TRUE.
  9842.  
  9843. 3 COMMENT_SIZE
  9844. To  prevent  coders  from entering empty comments  to  fool  the
  9845. style checker, the average size of comments (in characters) over
  9846. the  whole  program  must  be greater  than  'comment-size' or a
  9847. style flaw will be noted.
  9848.  
  9849. 3 PERCENT_LITERALS
  9850. The use of literal values such as numeric constants  or  strings
  9851. in   the   body  of a   program   significantly   reduces    the
  9852. maintainability  of the  program. Literals should preferably  be
  9853. in   the  declaration  to  give  them   greater  visibility  and
  9854. modifiability.   This  parameter is the maximum allowable amount
  9855. of literals allowed in the program  bodies.   The  number is the
  9856. percentage of literals in the  bodies  compared  to all literals
  9857. in the program.
  9858.  
  9859. If the program's percentage of literals in the bodies is greater
  9860. than 'percent-literals', then a style flaw is noted.
  9861.  
  9862. 3 PERCENT_UNIVERSAL
  9863. Programmers which  are  used to restricted  data  typing such as
  9864. Fortran's integer and real, may not initially use the freedom to
  9865. create types which  Ada allows. In  addition,  some  programmers
  9866. may only use the universal types (integer) out of laziness.   To
  9867. discourage the exclusive  use  of universal types, the style can
  9868. check the  percentage  of  universal  types  used as compared to
  9869. other user-defined numeric types.
  9870.  
  9871. If  the  average  percentage  of universal types is greater than
  9872. 'percent-universal', a style flaw will be noted.
  9873.  
  9874. 3 DATA_STRUCTURES
  9875. Programmers use to more  primitive languages  such as Fortran or
  9876. assembler  may  not  have  learned to use the  data  structuring
  9877. facilities  of  Ada  such  as records  or enumeration types.  If
  9878. the 'data-structures' flag is TRUE, the style checker will  note
  9879. whether  these  data  structuring  facilities  are  used  in the
  9880. program. If they are not used, a the style report will note that
  9881. fact  and  suggest  the   programmer   investigate  Ada's   data
  9882. structuring abilities.
  9883.  
  9884. 3 ATTRIBUTE_CHECK
  9885. The use of attributes is important for such purposes as limiting the
  9886. number of constants in the program.  The style definition includes
  9887. a parameter which tells the style checker to detect the use of
  9888. attributes in the input.  If the input contains NO attributes, a
  9889. flag is raised indicating potential for improvement by learning the
  9890. use of attributes.
  9891.  
  9892. 3 SUBPROGRAM_SIZE
  9893. The size of a subprogram  directly impacts its understandability
  9894. and   maintainability.  The  style  will   define  limits  on  a
  9895. subprogram's size, both  large and small.  This parameter is two
  9896. numbers limiting the size, in statements of  a  subprogram.   If
  9897. these  limits   are violated, a style flaw is noted.
  9898.  
  9899. 3 SUBPROGRAM_PARAMETERS
  9900. The number of parameters to a subprogram impacts its modularity.
  9901. The  style  defines  limits  on the number of parameters.  These
  9902. are both maximum and minimum limits.   The  applicable  function
  9903. will  return  two  numbers giving the limits for parameters.  If
  9904. limits are violated, a style flaw is noted.
  9905.  
  9906. 3 CONTROL_NESTING
  9907. If programs are nested too deeply this may indicate improper modularity.
  9908. This parameter indicates that nesting of control structures too deeply
  9909. be flagged as a style flaw.
  9910.  
  9911.  
  9912. 3 PACKAGE_NESTING
  9913. If programs are nested too deeply this may indicate improper modularity.
  9914. This parameter indicates that nesting of packages too deeply
  9915. be flagged as a style flaw.
  9916.  
  9917. 3 SUBPROGRAM_NESTING
  9918. If programs are nested too deeply this may indicate improper modularity.
  9919. This parameter indicates that nesting of subprograms too deeply
  9920. be flagged as a style flaw.
  9921.  
  9922. 3 NUMBER_OF_LOOP_EXITS
  9923. Structured programming limits the possible exits from a structure.
  9924. This parameter defines the limit on the number of exits.  If a
  9925. loop has more exit statements than defined by this parameter, a
  9926. style flaw is noted.
  9927.  
  9928. 3 LINE_SIZE
  9929. In transporting a program to a different machine, the new machine may impose
  9930. different limits on the size of lines.  This parameter allows the style
  9931. to flag lines which are longer than a certain size.  In this way, those
  9932. line which might have to be changed for transportability can be easily found.
  9933.  
  9934. 3 CHARACTER_SET
  9935. The LRM defines two different classes of characters.  The BASIC characters
  9936. are those required to be processable by any Ada system.  The GRAPHIC
  9937. characters are the additional normal characters which are usually available.
  9938. Since some machines may not support all characters, the style checker will
  9939. note special characters which may have to be changed for transportability.
  9940. This can also catch non-printing character which have inadvertently gotten
  9941. into the source.
  9942.  
  9943. The character classes allowed are (see LRM for complete definition):
  9944.      BASIC        -- Upper case letters, 0..9, punctuation
  9945.      GRAPHIC      -- Lower case letters, special punctuation:
  9946.                      ! $ % ? @ [ \ ] ^ ` { } ~
  9947.      EXTENDED     -- Other non-graphic ASCII characters, <ESC>, etc.
  9948.  
  9949. 3 REPRESENTATION_SPECS
  9950. Representation specifications are very non-transportable features in Ada.
  9951. The Style Checker can be told by this parameter to locate and flag uses
  9952. of representation specifications.  If this parameter is FALSE then
  9953. representation specifications are not allowed and are flagged as flaws.
  9954.  
  9955. 3 ADDRESS_CLAUSE
  9956. Address clauses are very non-transportable features in Ada.
  9957. The Style Checker can be told by this parameter to locate and flag uses
  9958. of address clauses.  If this parameter is FALSE then
  9959. address clauses are not allowed and are flagged as flaws.
  9960.  
  9961. 3 PRAGMAS
  9962. Pragmas may be compiler-dependant parts of a system.  This parameter tells
  9963. whether to flag occurrences of pragmas in the input.  The possible values
  9964. may be:
  9965.      ALL                 -- flag all pragmas
  9966.      SYSTEM-DEPENDENT    -- flag pragmas not defined in the LRM
  9967.      NONE                -- do not flag pragmas
  9968.  
  9969. 3 PREDEFINED_PRAGMA
  9970. This is not a parameter, but is a definition of which pragmas are defined
  9971. in the LRM.  This is a function called which returns TRUE if the input
  9972. pragma-name is defined in the LRM.  There are 14 predefined pragmas.
  9973.  
  9974. 3 PROSCRIBED_PACKAGE
  9975. The use of some packages depend highly on the supporting host.  These
  9976. packages may make transporting a system difficult.  The Style Checker
  9977. can be provided with a list of the packages which the user wants flagged.
  9978. These packages are called PROSCRIBED PACKAGES.
  9979.  
  9980. Typical packages might include UNCHECKED_CONVERSION, and SYSTEM.
  9981.  
  9982. These packages are defined by an array of strings naming the proscribed
  9983. packages.  The array is PROSCRIBED.
  9984.  
  9985. This is a special parameter in that its value must be changed in the
  9986. default definition of the parameter.  All other parameters are changed
  9987. in the SET_STYLE_PARAMETERS procedure.
  9988.  
  9989. 3 KEYWORD_PARAMETERS
  9990. The use of  each  Ada  reserved  word  may  be limited for style
  9991. purposes.  Each reserved word is specified separately. The usage
  9992. classes are
  9993.  
  9994.       *  Prohibited:  Any use at all is a style flaw.
  9995.  
  9996.       *  Restricted:   This  requires  a   second,   numeric
  9997.          parameter which is the maximum allowed frequency of
  9998.          the reserved word.  The number is the percentage of
  9999.          statements  which  may  contain  the reserved word.
  10000.          For  example,  if  the  number  is  0.05  then  the
  10001.          reserved  word  cannot  appear more than five times
  10002.          per 100 statements.
  10003.  
  10004.       *  Unlimited:  The reserved word can be used freely.
  10005.  
  10006.  
  10007.  
  10008. 2 STYLE_ISSUES_IN_GENERAL
  10009. This tool has been designed to provide a level of style checking to
  10010. give the user confidence that his system is following good guidelines.
  10011.  
  10012. Since few programmers agree completely on the correct way to structure code,
  10013. much of the style checking is dependent on a set of style parameters delivered
  10014. by the STYLE_PARAMETERS package.  These parameters are changable by altering
  10015. values in the body of that package.  For instructions on altering the style
  10016. values, see CHANGING_STYLE_PARAMETERS, below.
  10017.  
  10018. It should be noted that because of the wide variety in possible styles, some
  10019. compromises had to be made.  For example, checking indentation of comments
  10020. has basically been eliminated since so many people use different styles.
  10021. There are a few areas where it is possible to violate the "correct style" and
  10022. this program will not catch the error.  Usually this is the case so that
  10023. other correct style instances will not be caught along with the bad.
  10024.  
  10025. 3 CHANGING_STYLE_PARAMETERS
  10026. Inside the STYLE_PARAMETERS package, the values of the parameters are
  10027. defined in two different places.  In the declarations for the BODY, the
  10028. default values are set.  These default values should not be changed so as
  10029. to provide a standard basic style.  (There is one exception noted below.)
  10030.  
  10031. The actual values are set in the SET_STYLE_PARAMETERS procedure which is
  10032. called in the STYLE_PARAMETERS body.  This is where new style parameter
  10033. values should be changed.
  10034.  
  10035. Most of the possible values are obvious, such as POSITIVE or BOOLEAN values.
  10036. There are a few special enumeration types used.  These types are defined
  10037. in the STYLE_PARAMETERS specification.
  10038.  
  10039. Exception: The only style parameter which should be changed in the
  10040. declarations rather than in the SET_STYLE_PARAMETERS procedure is
  10041. the PROSCRIBED variable, defining those packages which are to be
  10042. flagged as undesirable packages.  This should be changed in the
  10043. declaration itself.
  10044.  
  10045.  
  10046. 2 MAINTENANCE
  10047. For maintenance information look under the HELP file for INSTALLATION
  10048. instructions, or look at the MAINTENANCE manual in the documentation
  10049. directory
  10050.