!+ ! Tools Group ! Space Telescope Science Institute ! 3700 San Martin Drive ! Baltimore, MD 21218 ! ! NAME ! FIND_MACRO_DEPENDENCIES ! ! DESCRIPTION ! This module scans a VAX MACRO source file for any non "built-in" ! macros. These files are the most difficult of MMSGEN supported ! languages to parse. The routine ignores built-ins by reading a ! user-provided list of built-in MACRO mnemonics. This can also be ! pointed to via a logical name, and MMSGEN provides this file for ! you to modify. ! ! MACRO comment lines are ignored. The key to this source in ! recognizing macros is by concatentating a single macro statement ! into a one line statement. This makes the parsing much simpler. ! ! RETURN VALUE ! ! HISTORY ! 11/88 Bauer First cut. !- MODULE FIND_MACRO_DEPENDENCIES; ! ! --- Set definitions --- ! SET blank ( ' ' ); SET horizontal_tab ( s'ht' ); SET form_feed ( s'ff' ); SET end_of_line ( s'eol' ); SET end_of_stream ( s'eos' ); SET open_paren ( '(' ); SET close_paren ( ')' ); SET open_bracket ( '[' ); SET close_bracket ( ']' ); SET ampersand ( '&' ); SET asterisk ( '*' ); SET colon ( ':' ); SET semi_colon ( ';' ); SET equal ( '=' ); SET comma ( ',' ); SET period ( '.' ); SET single_quote ( '''' ); SET double_quote ( '"' ); SET underscore ( '_' ); SET hyphen ( '-' ); SET dollar_sign ( '$' ); SET numeric_char ( '0'..'9' ); SET lower_alpha_char ( 'a'..'z' ); SET upper_alpha_char ( 'A'..'Z' ); SET alpha_char ( '_' OR lower_alpha_char OR upper_alpha_char OR '$'); SET alpha_num ( '.' OR alpha_char OR numeric_char ); SET white_space ( blank OR horizontal_tab OR form_feed ); SET non_white_space ( NOT ( blank OR horizontal_tab OR form_feed OR end_of_line OR end_of_stream ) ); SET any ( NOT ( end_of_line or end_of_stream ) ); ! ! --- Token definitions --- ! TOKEN ignore_spaces IGNORE { { white_space }... }; TOKEN period_T ALIAS '.' { '.' }; TOKEN continuation_T ALIAS '-' { '-' }; TOKEN id_T { alpha_char [alpha_num...] [':']}; TOKEN equal_T ALIAS '=' { '=' }; TOKEN eol_T { end_of_line }; DECLARE macro_mnemonics_file : EXTERNAL STRING; DECLARE problems_creating_complete_mms : EXTERNAL BOOLEAN; CONSTANT macro_mnemonics_file_C = 'MMSGEN$MACRO_MNEMONICS'; DECLARE macro_mnemonic_tree : GLOBAL TREE (STRING) OF BOOLEAN; DECLARE other_mnemonic_tree : GLOBAL TREE (STRING) OF BOOLEAN; DECLARE previous_id : GLOBAL STRING; DECLARE save_id : GLOBAL STRING; DECLARE previous_continuation_flag : GLOBAL BOOLEAN; DECLARE continuation_flag : GLOBAL BOOLEAN; DECLARE comment_flag : GLOBAL BOOLEAN; DECLARE macro_mnemonic_file_read : GLOBAL BOOLEAN; DECLARE first_id : GLOBAL BOOLEAN; DECLARE stop_scan_flag : GLOBAL BOOLEAN; ! ! --- MACRO definitions --- ! ! ! MACRO to recognize MACROs ! MACRO macro_directive_M TRIGGER { '.' [ s1: id_T [s2: id_T] ] FIND (s'eol') eol_T }; s1 = TRIM(UPPER(s1)); IF s1 = 'MACRO' THEN s2 = TRIM(UPPER(s2)); macro_mnemonic_tree(s2) = TRUE; ELSE IF s1 = 'END' THEN stop_scan_flag = TRUE; STOP SCAN; END IF; END IF; END MACRO; MACRO start_macro_M TRIGGER { s1,s2,col: id_T [eq: equal_T]}; IF save_id = '' THEN IF first_id AND eq = '' THEN IF INDEX(s1, ':') = 0 THEN save_id = s1; first_id = FALSE; END IF; ELSE first_id = FALSE; END IF; END IF; END MACRO; ! ! --- PROCEDURE definitions --- ! PROCEDURE read_macro_mnemonic_file; ! This reads in the built-in MACRO list DECLARE fp : FILE; DECLARE line : STRING; EXTERNAL PROCEDURE file_exists (STRING) OF BOOLEAN; IF macro_mnemonics_file = '' THEN macro_mnemonics_file = macro_mnemonics_file_C; IF NOT file_exists(macro_mnemonics_file) THEN WRITE '%MMSGEN-E-MISSINGMACRO, No MACRO file specified and ', macro_mnemonics_file, ' not defined.'; RETURN; END IF; END IF; OPEN FILE (fp) AS macro_mnemonics_file FOR INPUT; WHILE NOT ENDFILE(fp); READ FILE (fp) line; line = UPPER(line); IF line[1..1] <> '!' THEN macro_mnemonic_tree(line) = TRUE; END IF; END WHILE; CLOSE FILE (fp); END PROCEDURE; PROCEDURE check_on_macro ( what_macro : STRING); EXTERNAL PROCEDURE substitute_string (STRING, STRING, STRING); EXTERNAL PROCEDURE add_to_dependency_tree (STRING); EXTERNAL PROCEDURE add_to_plus_library_tree (STRING); EXTERNAL PROCEDURE filescan(STRING, STRING, STRING, STRING, STRING, STRING, STRING); EXTERNAL PROCEDURE search_libraries_for_module (STRING, STRING); EXTERNAL PROCEDURE find_module_in_library (STRING, STRING) OF BOOLEAN; DECLARE temp1, temp2 : STRING; DECLARE disk : STRING; DECLARE no_find : BOOLEAN; IF what_macro = '' THEN RETURN; END IF; what_macro = TRIM(UPPER(what_macro)); IF NOT EXISTS(macro_mnemonic_tree(what_macro)) THEN IF NOT EXISTS(other_mnemonic_tree(what_macro)) THEN no_find = TRUE; other_mnemonic_tree(what_macro) = TRUE; IF what_macro[1..1] = '$' THEN disk = 'SYS$LIBRARY:STARLET.MLB'; IF find_module_in_library (what_macro, disk) THEN ! temp1 = disk & '(' & what_macro & '=' & what_macro & '.MAR)'; temp1 = disk & '(' & what_macro & ')'; CALL add_to_dependency_tree (temp1); no_find = FALSE; END IF; END IF; IF no_find THEN CALL search_libraries_for_module (what_macro, disk); IF disk <> '' THEN ! temp1 = disk & '(' & what_macro & '=' & what_macro & '.MAR)'; temp1 = disk & '(' & what_macro & ')'; CALL add_to_dependency_tree (temp1); CALL add_to_plus_library_tree (disk); ELSE WRITE '%MMSGEN-E-CANFINDLIB, Include module ', what_macro, ' must map to a library.'; WRITE ' This will be omitted from the dependency list.'; problems_creating_complete_mms = TRUE; END IF; END IF; END IF; END IF; END PROCEDURE; PROCEDURE find_macro_dependencies (what_file : STRING); DECLARE dump_output : FIXED STRING(1); DECLARE total_line, line : STRING; DECLARe line_length : INTEGER; DECLARE fp : FILE; EXTERNAL PROCEDURE strip_macro_comments (STRING); PRUNE (other_mnemonic_tree); IF NOT macro_mnemonic_file_read THEN macro_mnemonic_file_read = TRUE; CALL read_macro_mnemonic_file; END IF; OPEN FILE (fp) AS what_file FOR INPUT; ! Read in MACRO source line by line stop_scan_flag = FALSE; WHILE NOT stop_scan_flag AND NOT ENDFILE(fp); ! Build up MACRO statements line = ''; READ FILE(fp) line; continuation_flag = TRUE; total_line = ''; WHILE continuation_flag; ! Especially those spread over many lines line = line & s'eol'; !write line; CALL strip_macro_comments (line); ! Trash any end-of-line comments line = TRIM(line, s'eol'); line = TRIM(line); !write line; line_length = LENGTH(line); IF line_length > 0 THEN IF line[line_length..line_length] = '-' ! Continuation line? THEN total_line = total_line & line[1..line_length-1]; continuation_flag = TRUE; ELSE total_line = total_line & line; continuation_flag = FALSE; END IF; END IF; IF continuation_flag THEN IF NOT ENDFILE(fp) THEN READ FILE(fp) line; ELSE continuation_flag = FALSE; END IF; END IF; END WHILE; first_id = TRUE; save_id = ''; comment_flag = FALSE; ! write total_line; START SCAN ! SCAN the complete statement for macros INPUT STRING total_line & s'eol' OUTPUT STRING dump_output; IF NOT stop_scan_flag THEN IF save_id <> '' THEN CALL check_on_macro (save_id); END IF; END IF; END WHILE; CLOSE FILE (fp); END PROCEDURE; END MODULE;