module MACRO_PASS_M use INPUT_M, only: INUNIT, READ_LINE use IO_UNITS, only: MACRO_FILE => MACROS, U_MACROS, U_SCR2 use MACHINE, only: IO_ERROR use OP_CODES_M, only: OP_CODES implicit NONE private public :: MACRO_PASS contains subroutine MACRO_PASS ! Process the input file, expanding macros, and including INCLD and ! CALL macros. integer, parameter :: MAX_MACROS = 99 character(5) :: CMD logical :: FOUND_MACRO ( max_macros ) integer :: I, J integer :: IOSTAT character(len=80) :: LINE_IN, LINE_MAC character(len=5) :: MACROS(max_macros) ! CALL and INCLD held until END integer :: N_MACROS n_macros = 0 o:do call read_line ( line_in, iostat ) if ( iostat < 0 ) exit ! End of file if ( iostat > 0 ) then ! Error call io_error ( "While reading input", inunit, macro_file ) stop end if if ( line_in(5:5) == '*' .or. line_in(16:18) == ' ' ) then write ( u_scr2, 100 ) ' ', line_in 100 format ( a5, a ) else do i = 1, size(op_codes,1)-1 if ( line_in(16:20) == op_codes(i)%op ) then if ( line_in(16:20) == 'END ' .or. line_in(16:20) == 'EX ' .or. & & line_in(16:20) == 'LTORG' ) call include_closed_macros write ( u_scr2, 100 ) ' ', trim(line_in) cycle o end if end do select case ( line_in(16:20) ) case ( 'CALL ' ) write ( u_scr2, 100 ) 'MACRO', trim(line_in) cmd = 'B' i = 21 do call get_arg if ( line_in(i:j-1) == '' ) exit if ( cmd == 'B' ) call add_macro ( line_in(i:j-1) ) write ( u_scr2, 200 ) 'GEN ', cmd, line_in(i:j-1) 200 format ( a5, 15x, a5, a ) if ( line_in(j:j) /= ',' ) exit i = j + 1 cmd = 'DCW' end do case ( 'INCLD' ) write ( u_scr2, 100 ) 'MACRO', trim(line_in) do i = 21, 25 if ( line_in(i:i) == ' ' ) exit end do call add_macro ( line_in(21:i) ) case default end select end if end do o contains subroutine ADD_MACRO ( NAME ) ! Add name of macro to be included at END or EX or LTORG character(len=*), intent(in) :: NAME do i = 1, n_macros if ( macros(i) == name ) return end do n_macros = n_macros + 1 if ( n_macros > max_macros ) then write ( u_scr2, '(a5,a)' ) 'ERROR', '* TOO MANY MACROS' else macros(n_macros) = name end if end subroutine ADD_MACRO subroutine GET_ARG ! Get an argument for a macro. Start at I, and go until the end ! of the argument -- a comma or blank not inside of @...@. if ( line_in(i:i) == '@' ) then j = 72 do if ( line_in(j:j) == '@' ) then j = j + 1 exit end if j = j - 1 end do else j = i do if ( line_in(j:j) == ',' .or. line_in(j:j) == ' ' ) exit j = j + 1 end do end if end subroutine GET_ARG subroutine INCLUDE_CLOSED_MACROS ! Include macros requested by CALL or INCLD. logical :: COPYING copying = .false. found_macro = .false. rewind ( u_macros ) m:do read ( u_macros, '(a)', iostat=iostat ) line_mac if ( iostat < 0 ) exit ! End of file if ( iostat > 0 ) then ! Error call io_error ( "While reading macros", inunit, macro_file ) stop end if if ( line_mac(16:20) == 'HEADR' ) then do i = 1, n_macros if ( line_mac(6:11) == macros(i) ) then if ( found_macro(i) ) then write ( u_scr2, 100 ) 'ERROR', & & '* DUPLICATE MACRO ON MACRO FILE: ' // trim(macros(i)) 100 format ( a5, a ) else copying = .true. found_macro(i) = .true. cycle m end if end if end do copying = .false. else if ( copying ) then write ( u_scr2, 100 ) 'GEN ', line_mac end if end do m do i = 1, n_macros if ( .not. found_macro(i) ) then write ( u_scr2, 100 ) 'ERROR', '* MACRO NOT FOUND: ' // trim(macros(i)) end if end do end subroutine INCLUDE_CLOSED_MACROS end subroutine MACRO_PASS end module MACRO_PASS_M