-1

I am trying to modernize a Fortran 77 codebase which makes heavy use of common blocks in include files. One of my goals is to translate the codebase so it uses modules instead of this common/include construction. However, the code also uses equivalence statements here and there, referring to common variables. It is not allowed to equivalence to/from module variables, so this is a problem.

Now, luckily, the equivalence statements are only used to alias (parts of) arrays and never for 'magic' between different variables types. Therefore I have tried to translate the code by simply calculating index offsets and referring to the original arrays instead of equivalenc-ing them. However, this has lead to some unexpected compilation errors and runtime crashes.

For example, consider the change from

IF(RLX*ABS(DXT/(X2-X1)) .GT. 0.05) RLX = 0.05*ABS((X2-X1)/DXT)

to

IF(RLX*ABS(DXT/(COM2(1)-COM1(1))) .GT. 0.05) RLX = 0.05*ABS((COM2(1)-COM1(1))/DXT)

, which is supposed to change the include file code from

REAL COM1(NCOM), COM2(NCOM)
COMMON/V_VAR1/ X1
COMMON/V_VAR2/ X2
EQUIVALENCE (X1, COM1(1)), (X2, COM2(1))

to simply

COMMON COM1(NCOM), COM2(NCOM)

, but leads to the following compilation error:

       IF(RLX*ABS(DXT/(COM2(1)-COM1(1))) .GT. 0.05) RLX = 0.05*ABS((COM2(1)-COM1(1))/DXT)
                                                                        1
Error: Missing ')' in statement at or before (1)

This statement seems correct to me, though. So what am I missing here?

If I alleviate the above problem by changing the code to

DX = COM2(1) - COM1(1)
IF(RLX*ABS(DXT/DX) .GT. 0.05) RLX = 0.05*ABS(DX/DXT)

I do not get compilation errors. However, then I run into Signal: SIGFPE (Arithmetic exception)'s at runtime, because for some reason the change from X1 to COM1(1) and X2 to COM2(1) leads to seemingly unrelated variables to not get proper initial values (which leads to division by zero, and consequently to the addition of nan's, and therefore to the arithmetic exception).

Obviously, I am missing something crucial here, so I tried to find a good reference for doing this sort of translation. Does anyone know of something like that? Or has anyone run into this problem before and found a solution? Any help would be greatly appreciated.

D. de Vries
  • 417
  • 3
  • 12
  • 6
    Adding extra characters to a line can easily push a line length beyond the limit, so please check how long that new line is. Also, the "simplified" single line is very different from the three lines it replaces, having `ncom` times the number of numeric storage units specified in the common block. – francescalus Jan 07 '19 at 22:56
  • 2
    Are you restricted to fixed format you can you use free format in the new code? If you are modernizing the code, I don’t see any sense in writing it in fixed format again. – Rodrigo Rodrigues Jan 07 '19 at 23:35
  • 1
    Also consider modernizing all the CAPITAL letters and the ugly `.GT.` to `>`. But I do agree one should not change too much at once before testing the change. I also agree that your error looks like a line length limit issue (plenty of duplicates available). – Vladimir F Героям слава Jan 08 '19 at 07:32
  • @francescalus The new line is 89 characters long, so I don't think that ought to be a problem, right? I don't understand what you mean about the simplification of the include file code. In the original code, there were two arrays of type `real` and length `ncom`, `com1` and `com2`, the first elements of which were equivalenced to two `real`s, `x1` and `x2`. In the simplified case, there are only the `com1` and `com2` arrays, the first elements of which are used _directly_ in the changed code above, instead of through their equivalence. Would that not work as I expect it? – D. de Vries Jan 08 '19 at 13:04
  • @RodrigoRodrigues No, I am definitely not bound to the fixed format. But like @VladimirF said, I will change things one step at a time. In fact, I am going to use [plusFORT](https://www.polyhedron.com/plusfort7) to take care of most of the translation to F90 after getting rid of the `equivalence` statements. – D. de Vries Jan 08 '19 at 13:07
  • 2
    89 characters are too many in Fortran 77 (more generally, fixed-form source). – francescalus Jan 08 '19 at 13:20
  • 1
    In the first version you have that the (blank) common block has two scalars: `X1` and `X2`. In the second version the blank common block has two arrays `COM1` and `COM2`, each with `NCOM` elements. If `NCOM` is not `1` those two specifications are different. – francescalus Jan 08 '19 at 13:22
  • @francescalus Ah, now I see what you mean. And you're right! That is weird. This is how the original source had done it. They declare local arrays of length `ncom`, and global (`common`) scalars, and equivalence the first elements of the local arrays to the global scalars. But then they do proceed to use the arrays as well in the functions which include this file. Does that mean the content of those arrays are then unique and independent to each function including this file (with the exception of the first elements, because those are `common`)? – D. de Vries Jan 08 '19 at 13:30
  • 1
    Looks like I neglected something pretty important about the first common statement: because `x1` and `x2` are in common and the equivalence, you actually have an association between the array elements of `com1` and `com2` (`com1(2)` is the same lump of memory as `com2(1)`) . The second version doesn't capture this. If you want more information about that, I'd suggest trying to get a question zooming in on that. – francescalus Jan 08 '19 at 13:37
  • @francescalus Well, actually, it turns out I also forgot an important difference. The two scalars, `x1` and `x2`, are actually written as `common/v_var1/ x1` and `common/v_var2/ x2`. In this case the link you described between the elements of `com1` and `com2` does not exist. – D. de Vries Jan 08 '19 at 13:54
  • 2
    From [F2008 Standard, section 3.3.3](https://j3-fortran.org/doc/year/10/10-007.pdf) _In fixed source form, there are restrictions on where a statement may appear within a line. **If a source line contains only characters of default kind, it shall contain exactly 72 characters;** otherwise, its maximum number of characters is processor dependent._ – kvantour Jan 08 '19 at 16:15
  • In case the conversion of old (legacy) Fortran to a modern style is the main topic, this forum https://groups.google.com/forum/#!forum/comp.lang.fortran might also be useful (more suited for long posts and discussion, e.g., using a link to external codes in Github/Gist etc) – roygvib Jan 10 '19 at 19:01

1 Answers1

0

As pointed in the comments, the error arises after refactoring the code probably because you are working in fixed-form and the source line cannot go beyond 72 characters (all the remaining characters are ignored).

If you are modernizing the code, you should left fixed-form behind and write in free-form. Sometimes compilers assume source-form based on file extension. If this is the case, you can change the file extension from .f to .f90. Or else, you can pass the desired format as a compiler flag (-ffree-form in gfortran, -free in Intel Fortran).

If by any case you are stuck into fixed-form, you'd better do a line-continuation by putting an arbitrary non-blank character at column 6 of the continued line.

Rodrigo Rodrigues
  • 7,545
  • 1
  • 24
  • 36