Препроцессоры и ассоциации использования - PullRequest
4 голосов
/ 07 февраля 2012

Таким образом, можно ли через ассоциацию использования получить доступ к директиве препроцессора, определенной в модуле Fortran?

Контекст

Я использую операторы препроцессора для определения подпрограмм дляпечатать предупреждения и сообщения об ошибках.Например, я использую следующий модуль / подпрограмму в файле errors.f для печати предупреждающих сообщений

module errors
  use, intrinsic :: iso_fortran_env, only : error_unit=>stderr
  implicit none
  contains

    !> Print formatted warning message.
    subroutine warn_print( file, line, mesg )
      implicit none
      character(len=*), intent(in) :: file
      integer,          intent(in) :: line
      character(len=*), intent(in) :: mesg

      write(stderr,'(a,a,a,i4,a,a)') "WARNING::", file, ":", line, ": ", mesg

  end subroutine warn_print

end module errors

и в отдельном файле errors.h, I use вышеупомянутого модуля и определяюмакрос препроцессора

use errors

#define warn( text )warn_print(__FILE__,__LINE__,text)

Затем я #include файл errors.h, в каком бы файле / модуле я не хотел использовать процедуру печати предупреждений, которая позволяет мне просто писать

call warn("Some warning message")

и компилятор автоматически включит файл и номер строки, по которой было вызвано предупреждающее сообщение.

Вопрос

Использование #include 'errors.h' довольно необычно в коде Фортранаи он скрывает use модуля errors.В идеале я бы предпочел определить вышеупомянутый препроцессор в самом модуле ошибок.Однако при использовании этого модуля эта директива препроцессора недоступна программе / модулю, который use s этот модуль.

Есть ли способ сделать директиву препроцессора доступной через ассоциацию использования?

Единственный другой способ, которым я могу думать об этом, это просто иметь модуль ошибок и определить директиву препроцессора в моем вызове компилятору (используя, например, флаг -D с ifort).Будем весьма благодарны за любые предложения по альтернативному способу достижения вышеуказанного.

Ответы [ 2 ]

2 голосов
/ 07 февраля 2012

Нет, это просто невозможно, поскольку этапы предварительной обработки и компиляции полностью отделены друг от друга, а препроцессор C ничего не знает об операторе USE Fortran.

Я использую #include 'config.h' (из autoconf) в большинстве моих .F90-источников без проблем.

1 голос
/ 08 февраля 2012

Возможно, это не то, что вы ищете, но если вы используете ifort, вы можете использовать функцию трассировки для достижения чего-то похожего (немного более мощного, но и более уродливого), например,

program tracetest
  call sub(5)
  write(*,*) '=== DONE ==='
end program tracetest

subroutine sub(n)
  use ifcore
  integer :: n
  character(len=60) :: str
  write(str,*) '=== TROUBLE DETECTED: n =',n  ! code -1 means "do not abort"      
  call tracebackqq(str,-1)    
end subroutine sub

Затем скомпилируйте с -traceback, чтобы увидеть исходный файл, строку и трассировку стека.Трассировка и линия стека могут быть скрыты из-за встраивания;чтобы избежать этого, вы можете указать -traceback -O0, чтобы получить что-то вроде этого:

=== TROUBLE DETECTED: n =           5                      
Image              PC                Routine            Line        Source             
a.out              0000000000473D0D  Unknown               Unknown  Unknown
a.out              0000000000472815  Unknown               Unknown  Unknown
a.out              0000000000423260  Unknown               Unknown  Unknown
a.out              0000000000404BD6  Unknown               Unknown  Unknown
a.out              0000000000402C14  sub_                       12  tracetest.f90
a.out              0000000000402B18  MAIN__                      2  tracetest.f90
a.out              0000000000402ADC  Unknown               Unknown  Unknown
libc.so.6          000000323201EC5D  Unknown               Unknown  Unknown
a.out              00000000004029D9  Unknown               Unknown  Unknown
=== DONE ===

В качестве альтернативы, если вы хотите сохранить оптимизации, а также хотите увидеть правильную строку (12), вы можете скомпилировать с(например) -fast -traceback -debug all,inline_debug_info.Нечто подобное может быть доступно и в других компиляторах, но я не уверен.

...