If this is the case, I think that the approach you proposed is the best way to go. However, since you want to add complex input functionality, I would suggest creating routines for real and complex types separately in a module and then use them in the main program:
module defs
implicit none
private
public :: work
interface work
module procedure :: work_r
module procedure :: work_c
end interface work
contains
subroutine work_r(x)
real, intent(out) :: x
x = (2.5, 3.1)
end subroutine
subroutine work_c(x)
complex, intent(out) :: x
x = (2.5, 3.1)
end subroutine
end module defs
program main
use defs, only: work
implicit none
real :: x
complex :: y
call work(x)
call work(y)
print*, x
print*, y
end program main
To generate this module from the program that you already have, I would suggest you take a look at Fypp, a thread was opened here recently.