!+ ! Tools Group ! Space Telescope Science Institute ! 3700 San Martin Drive ! Baltimore, MD 21218 ! ! NAME ! MMSGEN (Main Program) ! ! DESCRIPTION ! This is the main module for the MMSGEN (MMS Generator) tool. ! ! RETURN VALUE ! ! HISTORY ! 11/88 Bauer First cut. !- MODULE MMSGEN$MAIN; ! ! Constant Declarations ! CONSTANT CLI$_DEFAULTED EXTERNAL INTEGER; CONSTANT CLI$_NEGATED EXTERNAL INTEGER; ! End of input list hit CONSTANT CLI$_ABSENT EXTERNAL INTEGER; ! End of input list hit CONSTANT CLI$_PRESENT EXTERNAL INTEGER; ! Qualifier exists CONSTANT CLI$_LOCPRES EXTERNAL INTEGER; ! Local qualifier exists CONSTANT SS$_NORMAL EXTERNAL INTEGER; ! Good status EXTERNAL PROCEDURE file_exists (STRING) OF BOOLEAN; EXTERNAL PROCEDURE filescan (STRING, STRING, STRING, STRING, STRING, STRING, STRING); EXTERNAL PROCEDURE lib$get_foreign ( DESCRIPTOR STRING, DESCRIPTOR STRING, REFERENCE INTEGER, REFERENCE INTEGER ) OF INTEGER; EXTERNAL PROCEDURE lib$find_file ( DESCRIPTOR STRING, DESCRIPTOR STRING, REFERENCE INTEGER, DESCRIPTOR STRING, DESCRIPTOR STRING, REFERENCE INTEGER, REFERENCE INTEGER ) OF BOOLEAN; EXTERNAL PROCEDURE lib$find_file_end ( REFERENCE INTEGER ); EXTERNAL PROCEDURE lib$stop ( VALUE INTEGER ); EXTERNAL PROCEDURE lib$do_command ( DESCRIPTOR STRING ); EXTERNAL PROCEDURE substitute_string ( STRING, STRING, STRING ); EXTERNAL PROCEDURE substitute_all_strings ( STRING, STRING, STRING ); ! ! --- Global data --- ! DECLARE master_target : GLOBAL STRING; DECLARE master_target_tree : GLOBAL TREE(INTEGER) OF STRING; DECLARE master_target_tree_count : GLOBAL INTEGER; DECLARE target_extension : GLOBAL STRING; DECLARE problems_creating_complete_mms : GLOBAL BOOLEAN; DECLARE preface_file : GLOBAL STRING; DECLARE macro_mnemonics_file : GLOBAL STRING; DECLARE ignore_system_flag : GLOBAL BOOLEAN; DECLARE logging : GLOBAL BOOLEAN; DECLARE action_tree : GLOBAL TREE(STRING) OF STRING; DECLARE compile_mms_tree : GLOBAL TREE(INTEGER) OF STRING; DECLARE compile_mms_tree_count : GLOBAL INTEGER; DECLARE concat_string : GLOBAL STRING; DECLARE output_disk : GLOBAL STRING; DECLARE output_directory : GLOBAL STRING; DECLARE output_path : GLOBAL STRING; DECLARE output_file_count : GLOBAL INTEGER; DECLARE output_file : GLOBAL STRING; DECLARE dependency_tree : GLOBAL TREE (INTEGER) OF STRING; DECLARE dependency_tree_count : GLOBAL INTEGER; DECLARE used_dependency_tree : GLOBAL TREE (STRING) OF BOOLEAN; DECLARE library_tree_count : GLOBAL INTEGER; DECLARE library_tree : GLOBAL TREE (INTEGER) OF STRING; DECLARE plus_library_tree_count : GLOBAL INTEGER; DECLARE plus_library_tree : GLOBAL TREE (INTEGER) OF STRING; DECLARE used_plus_library_tree : GLOBAL TREE (STRING) OF BOOLEAN; DECLARE other_dependency_tree_count : GLOBAL INTEGER; DECLARE other_dependency_tree : GLOBAL TREE (INTEGER) OF STRING; DECLARE test_dependency_flag : GLOBAL BOOLEAN; DECLARE execute_flag : GLOBAL BOOLEAN; DECLARE execute_string : GLOBAL STRING; DECLARE one_mms_flag : GLOBAL BOOLEAN; DECLARE used_input_file_tree : GLOBAL TREE(STRING) OF BOOLEAN; DECLARE input_file_tree : GLOBAL TREE(INTEGER) OF STRING; DECLARE input_file_count : GLOBAL INTEGER; DECLARE command_line : GLOBAL STRING; DECLARE target_string : GLOBAL STRING; DECLARE target_disk : GLOBAL STRING; DECLARE target_directory : GLOBAL STRING; ! ! --- PROCEDURE definitions --- ! PROCEDURE add_to_dependency_tree (include_file : STRING); ! Add file to dependency list DECLARE temp : STRING; temp = UPPER(TRIM(include_file)); CALL substitute_all_strings ( ' ', '', temp); IF EXISTS(used_dependency_tree(temp)) THEN IF logging THEN WRITE '%MMSGEN-I-SAME_INCLUDE, Include file ', include_file, ' is listed more than once.'; END IF; ELSE IF ignore_system_flag AND INDEX(temp, 'SYS$LIBRARY:') > 0 THEN ELSE dependency_tree_count = dependency_tree_count + 1; dependency_tree(dependency_tree_count) = temp; used_dependency_tree(temp) = TRUE; END IF; END IF; END PROCEDURE; PROCEDURE add_to_plus_library_tree (library : STRING); ! Add to plus library tree for ! compilation line DECLARE temp : STRING; temp = UPPER(TRIM(library)); IF NOT EXISTS(used_plus_library_tree(temp)) THEN plus_library_tree_count = plus_library_tree_count + 1; plus_library_tree(plus_library_tree_count) = temp; used_plus_library_tree(temp) = TRUE; END IF; END PROCEDURE; PROCEDURE construct_input_files_tree (from_what : STRING); ! Get input files list first DECLARE context : INTEGER; DECLARE nextfile : STRING; DECLARE node, disk, directory, dummy : STRING; DECLARE source_area1, input_file, filename, extension : STRING; DECLARE input_list : TREE(INTEGER) OF STRING; DECLARE input_list_cnt : INTEGER; DECLARE i : INTEGER; DECLARE line : STRING; DECLARE fp : FILE; CALL filescan (from_what, dummy, disk, directory, dummy, extension, dummy); IF extension = '.SOURCE_LIST' THEN OPEN FILE (fp) AS from_what FOR INPUT; input_list_cnt = 0; WHILE NOT ENDFILE(fp); READ FILE (fp) line; IF line[1..1] <> '!' THEN input_list_cnt = input_list_cnt + 1; input_list(input_list_cnt) = line; END IF; END WHILE; CLOSE FILE (fp); ELSE input_list_cnt = 1; input_list(input_list_cnt) = from_what; END IF; i = 1; WHILE i <= input_list_cnt; from_what = input_list(i); CALL filescan (from_what, dummy, disk, directory, dummy, dummy, dummy); source_area1 = disk & directory; ! write 'Source_area1> ', source_area1; context = 0; WHILE lib$find_file(from_what, nextfile, context, *,*,*,*); CALL filescan (nextfile, node, disk, directory, filename, ! This will handle a stretched logical so extension, dummy); ! the same source is not repeated input_file = source_area1 & filename & extension; IF NOT EXISTS(used_input_file_tree(input_file)) THEN used_input_file_tree(input_file) = TRUE; input_file_count = input_file_count + 1; input_file_tree (input_file_count) = input_file; END IF; END WHILE; CALL lib$find_file_end( context ); i = i + 1; END WHILE; ! write 'Input_file_cout = ', input_file_count; END PROCEDURE; PROCEDURE copy_preface (to_fp : FILE); ! Copy preface file DECLARE fp : FILE; DECLARE line : STRING; OPEN FILE (fp) AS preface_file FOR INPUT; WHILE NOT ENDFILE(fp); READ FILE (fp) line; WRITE FILE (to_fp) line; END WHILE; CLOSE FILE (fp); END PROCEDURE; PROCEDURE write_output_mms_file (output_file : STRING); ! Write MMS to disk DECLARE i : INTEGER; DECLARE fp : FILE; IF logging THEN WRITE '%MMSGEN-I-OUT_MMS_IS, Creating output MMS file: ', output_file; END IF; OPEN FILE (fp) AS output_file FOR OUTPUT; IF preface_file <> '' THEN CALL copy_preface (fp); END IF; IF master_target <> '' THEN WRITE FILE (fp) master_target, ' : -'; FOR i = 1 to master_target_tree_count-1 STEP 1; WRITE FILE (fp) ' ', master_target_tree(i), ', -'; END FOR; WRITE FILE (fp) ' ', master_target_tree(i); WRITE FILE (fp) ' ! $(MMS$TARGET) Updated '; WRITE FILE (fp) ' '; END IF; FOR i = 1 TO compile_mms_tree_count STEP 1; WRITE FILE (fp) compile_mms_tree(i); END FOR; CLOSE FILE (fp); output_file_count = output_file_count + 1; END PROCEDURE; PROCEDURE check_dependencies; ! Check MMS dependencies DECLARE i : INTEGER; DECLARE check_file : STRING; FOR i = 1 to dependency_tree_count STEP 1; IF INDEX(dependency_tree(i), '(') > 0 THEN check_file = dependency_tree(i)[1..(INDEX(dependency_tree(i),'(')-1)]; ELSE check_file = dependency_tree(i); END IF; IF NOT file_exists(check_file) THEN WRITE '%MMSGEN-I-MISSING_DEPENDENCY, Can''t find dependency: ', check_file; IF execute_flag THEN WRITE '%MMSGEN-I-WONT_EXECUTE, Will not execute output MMS as instructed.'; execute_flag = FALSE; END IF; END IF; END FOR; END PROCEDURE; PROCEDURE write_compile_mms_tree (mms_target : STRING, ! Write compile MMS to memory source: STRING, source_language : STRING); DECLARE i : INTEGER; compile_mms_tree_count = compile_mms_tree_count + 1; compile_mms_tree(compile_mms_tree_count) = mms_target & ' : ' & source; FOR i = 1 to dependency_tree_count STEP 1; compile_mms_tree(compile_mms_tree_count) = compile_mms_tree(compile_mms_tree_count) & ', -'; compile_mms_tree_count = compile_mms_tree_count + 1; compile_mms_tree(compile_mms_tree_count) = ' ' & dependency_tree(i); END FOR; FOR i = 1 to other_dependency_tree_count STEP 1; compile_mms_tree(compile_mms_tree_count) = compile_mms_tree(compile_mms_tree_count) & ', -'; compile_mms_tree_count = compile_mms_tree_count + 1; compile_mms_tree(compile_mms_tree_count) = ' ' & other_dependency_tree(i); END FOR; compile_mms_tree_count = compile_mms_tree_count + 1; compile_mms_tree(compile_mms_tree_count) = ' ' & action_tree(source_language); FOR i = 1 to plus_library_tree_count; compile_mms_tree(compile_mms_tree_count) = compile_mms_tree(compile_mms_tree_count) & ' + ' & plus_library_tree(i) & '/LIBRARY'; END FOR; CALL substitute_string ('%%', source, compile_mms_tree(compile_mms_tree_count)); compile_mms_tree_count = compile_mms_tree_count + 1; compile_mms_tree(compile_mms_tree_count) = ''; END PROCEDURE; PROCEDURE setup_default_actions; ! Set up default action tree action_tree('.EQF') = '$(EQF) %% $(DATABASE) $(FFLAGS)'; action_tree('.EQE') = '$(EQF) %% $(DATABASE) $(FFLAGS)'; action_tree('.FOR') = '$(FORT) $(FFLAGS) %%'; action_tree('.MSG') = 'MESSAGE/OBJECT=$(MMS$TARGET) %%'; action_tree('.X') = '$(XC) $(XFLAGS) %% -o $(MMS$TARGET)'; action_tree('.FBL') = '$(FORT) $(FFLAGS) %%'; action_tree('.C') = '$(CC) $(CFLAGS) %%'; action_tree('.SCN') = 'SCAN/OBJECT=$(MMS$TARGET) $(SCANFLAGS) %%'; action_tree('.MAR') = '$(MACRO) $(MFLAGS) %%'; action_tree('.MBL') = '$(MACRO) $(MFLAGS) %%'; END PROCEDURE; !+ ! NAME ! parse_command_line -- extracts CLD parameters for tool ! ! DESCRIPTION ! This routine parses the infinite command line possiblities ! for this tool. ! ! RETURN VALUE ! ! HISTORY ! 11/88 Bauer Initial implementation. ! !- PROCEDURE parse_command_line; EXTERNAL PROCEDURE cli$get_value (STRING, STRING, INTEGER) OF INTEGER; ! CLI system routine EXTERNAL PROCEDURE cli$present (STRING) OF INTEGER; ! CLI system routine EXTERNAL PROCEDURE sys$exit ( VALUE INTEGER ); DECLARE dummy : INTEGER; ! Dummy parameter DECLARE node : STRING; DECLARE dummy_string : STRING; ! Dummy parameter DECLARE ret_status : INTEGER; ! Have to return status somewhere DECLARE input_file_name : STRING; ! Log file name DECLARE temp : STRING; ! Dummy string DECLARE new_action : STRING; DECLARE extension : STRING; DECLARE filename : STRING; WHILE cli$get_value('from_what', input_file_name, dummy) ! Get all LOG file names <> CLI$_ABSENT; CALL construct_input_files_tree (input_file_name); END WHILE; IF cli$present ('target') = CLI$_PRESENT THEN ret_status = cli$get_value('target', temp, dummy); CALL filescan (temp, dummy_string, target_disk, target_directory, dummy_string, dummy_string, dummy_string); target_string = target_disk & target_directory; ELSE target_string = ''; END IF; IF cli$present('concat') = CLI$_PRESENT THEN ret_status = cli$get_value('concat', concat_string, dummy); concat_string = TRIM(concat_string, '"'); concat_string = TRIM(concat_string); ELSE concat_string = ''; END IF; IF cli$present ('output') = CLI$_PRESENT ! Get output file name THEN ret_status = cli$get_value('output', temp, dummy); CALL filescan (temp, node, output_disk, output_directory, filename, dummy_string, dummy_string); output_path = node & output_disk & output_directory; IF filename <> '' THEN one_mms_flag = TRUE; output_file = output_path & filename & concat_string & '.MMS'; ELSE one_mms_flag = FALSE; END IF; ELSE output_path = ''; one_mms_flag = FALSE; END IF; IF cli$present ('test_dependency') = CLI$_PRESENT THEN test_dependency_flag = TRUE; ELSE test_dependency_flag = FALSE; END IF; IF cli$present ('system') = CLI$_NEGATED THEN ignore_system_flag = TRUE; ELSE ignore_system_flag = FALSE; END IF; IF cli$present ('log') = CLI$_NEGATED THEN logging = FALSE; ELSE logging = TRUE; END IF; IF cli$present ('execute') = CLI$_PRESENT THEN execute_flag = TRUE; test_dependency_flag = TRUE; IF cli$get_value ('execute', temp, dummy) = SS$_NORMAL THEN execute_string = temp; execute_string = execute_string[2..(LENGTH(execute_string)-1)]; CALL substitute_all_strings ( '""', '"', execute_string); ELSE execute_string = ''; END IF; ELSE execute_flag = FALSE; END IF; IF cli$present ('target_extension') = CLI$_PRESENT THEN ret_status = cli$get_value ('target_extension', target_extension, dummy); CALL filescan (target_extension, dummy_string, dummy_string, dummy_string, dummy_string, extension, dummy_string); target_extension = extension; ELSE target_extension = '.OBJ'; END IF; IF cli$present ('search_libraries') = CLI$_PRESENT THEN WHILE cli$get_value('search_libraries', input_file_name, dummy) ! Get all LOG file names <> CLI$_ABSENT; IF file_exists(input_file_name) THEN library_tree_count = library_tree_count + 1; library_tree(library_tree_count) = input_file_name; ELSE WRITE '%MMSGEN-E-LIBNOTFND, Search library ', input_file_name, ' not found.'; END IF; END WHILE; END IF; IF cli$present ('other_dependencies') = CLI$_PRESENT THEN WHILE cli$get_value('other_dependencies', temp, dummy) <> CLI$_ABSENT; other_dependency_tree_count = other_dependency_tree_count + 1; temp = temp[2..(LENGTH(temp)-1)]; CALL substitute_all_strings ( ' ', '', temp); temp = UPPER(temp); other_dependency_tree(other_dependency_tree_count) = temp; END WHILE; END IF; IF cli$present ('action') = CLI$_PRESENT THEN WHILE cli$get_value('action', temp, dummy) <> CLI$_ABSENT; temp = UPPER(temp); temp = temp[2..(LENGTH(temp)-1)]; IF INDEX(temp, '=') > 0 AND INDEX(temp, '.') > 0 AND INDEX(temp, '%%') > 0 THEN extension = temp[1..(INDEX(temp,'=')-1)]; new_action = temp[(INDEX(temp,'=')+1)..]; action_tree(extension) = new_action; ELSE WRITE '%MMSGEN-E-BADACTSYN, Illegal action syntax: "', temp, '". Action ignored.'; END IF; END WHILE; END IF; ret_status = cli$present ('macro_list'); IF ret_status = CLI$_PRESENT OR ret_status = CLI$_DEFAULTED THEN ret_status = cli$get_value('macro_list', macro_mnemonics_file, dummy); IF NOT file_exists(macro_mnemonics_file) THEN WRITE '%MMSGEN-E-MISSINGMACRO, MACRO mnemonics file ', macro_mnemonics_file, ' not found.'; END IF; END IF; ret_status = cli$present ('preface'); IF ret_status = CLI$_PRESENT OR ret_status = CLI$_DEFAULTED THEN ret_status = cli$get_value('preface', preface_file, dummy); IF NOT file_exists(preface_file) THEN WRITE '%MMSGEN-E-MISSINGPREFACE, MMS PREFACE file ', preface_file, 'not found.'; END IF; ELSE preface_file = ''; END IF; IF one_mms_flag THEN IF cli$present ('master_target') = CLI$_PRESENT THEN ret_status = cli$get_value('master_target', master_target, dummy); ELSE master_target = ''; END IF; END IF; ret_status = cli$get_value('$LINE', command_line, dummy); ! What command was entered END PROCEDURE; PROCEDURE mmsobjgen MAIN; DECLARE nextfile, node, disk, directory, filename, extension, version : STRING; DECLARE i : INTEGER; DECLARE mms_target : STRING; EXTERNAL PROCEDURE find_fortran_dependencies (STRING); EXTERNAL PROCEDURE find_c_dependencies (STRING); EXTERNAL PROCEDURE find_x_dependencies (STRING); EXTERNAL PROCEDURE find_macro_dependencies (STRING); EXTERNAL PROCEDURE find_scan_dependencies (STRING); EXTERNAL PROCEDURE write_compile_mms_file (STRING, STRING); EXTERNAL PROCEDURE check_dependencies; CALL setup_default_actions; ! Use a standard set of default rules master_target_tree_count = 0; CALL parse_command_line; ! Get command line and figure out what ! we're supposed to do. output_file_count = 0; i = 1; WHILE (i <= input_file_count); ! Process all input files... problems_creating_complete_mms = FALSE; PRUNE (used_dependency_tree); ! Always clear out these trees PRUNE (used_plus_library_tree); dependency_tree_count = 0; plus_library_tree_count = 0; nextfile = input_file_tree(i); ! Input file is ... CALL filescan (nextfile, node, disk, directory, filename, extension, version); ! This next is statement should be illegal ! but its not as bad as it might seem. IF extension = '.FOR' OR extension = '.FBL' ! FORTRAN source? OR extension = '.EQE' OR extension = '.EQF' THEN CALL find_fortran_dependencies (nextfile); ELSE IF extension = '.C' ! C source? THEN CALL find_c_dependencies (nextfile); ELSE IF extension = '.SCN' ! SCAN source? THEN CALL find_scan_dependencies (nextfile); ELSE IF extension = '.MSG' ! MESSAGE source? THEN ! No dependencies for message files ! ELSE IF extension = '.MAR' OR extension = '.MBL' ! MACRO source? THEN CALL find_macro_dependencies (nextfile); ELSE IF extension = '.X' ! X source? THEN CALL find_x_dependencies (nextfile); ELSE WRITE '%MMSGEN-E-UNKNOWN_LANG, Can''t make a compile MMS for ', nextfile, ', language unknown.'; END IF; END IF; END IF; END IF; END IF; END IF; mms_target = target_string & filename & target_extension; IF master_target <> '' ! Master target list? THEN master_target_tree_count = master_target_tree_count + 1; master_target_tree(master_target_tree_count) = mms_target; END IF; IF problems_creating_complete_mms THEN WRITE '%MMSGEN-I-PROBMMS, Problems creating complete MMS description for source file: ', nextfile; END IF; CALL write_compile_mms_tree (mms_target, nextfile, extension); ! Write MSM to memory first IF NOT one_mms_flag ! Write an output MMS? THEN output_file = output_path & filename & concat_string & '.MMS'; CALL write_output_mms_file (output_file); compile_mms_tree_count = 0; END IF; IF test_dependency_flag ! Check dependecies? THEN CALL check_dependencies; END IF; i = i + 1; END WHILE; IF one_mms_flag ! One MMS? THEN CALL write_output_mms_file (output_file); END IF; IF execute_flag AND output_file_count=1 ! Execute this? THEN IF logging THEN WRITE '$ MMS/DESCRIP=' & output_file & ' ' & execute_string; END IF; CALL LIB$DO_COMMAND ('MMS/DESCRIP=' & output_file & ' ' & execute_string); END IF; END PROCEDURE; END MODULE;