Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Blank space in variable name

renaud_egal_r_
Beginner
1,239 Views

Hello everybody,

is there a compiler option that can detect blank space in a variable name ? Currently, I have following code, and it works great. Except There are a lot of COMMON blocks all over the place, with variables with different name and even spaces(maybe even tabs) in it...

      ...
      SECTION TOTALE = 0.D+0
      DO I = 1, NOMBRE_PASSAGE
          PASSAGE = SEQUENCEL (I)
          ONDE  = TYPE_ONDE_C ( PASSAGE, ZONEENTREE )
          SECTIONTOTALE = SECTIONTOTALE + AC (ONDE)
      ENDDO
      ...

 

How can I find and replace them ?

Thks

Renaud

0 Kudos
1 Solution
jimdempseyatthecove
Honored Contributor III
1,239 Views

Luigi's recommendations in #7 should be followed. The only thing I can add is from experience several years ago in doing this very same thing with 13 projects with 750 files.

1) Use your favorite text processing program, AWK, PYTHON, etc. (I used TECO) to search all files for COMMON blocks and produce an output file containing the COMMON block, together with name and variables declared within. I produced this on a single line for each entry.

2) Sort the output file

3) Locate all commons with same name and identical variable lists for all instances of that name. These are likely safe to move directly into a module. I used MOD_NameThatWasUsedOnCOMMONblock. *** you should not assume that all said variables have same type - so verify. You remove from the list the entries you selected. Replace the COMMON declarations with USE MOD_... (in the appropriate place), then compile and test and verify correctness.

4) Locate all named commons with a single declaration, and do the same as in 3)

5) What you have left in the list (if any) are named commons that map the common block differently. Each instance will have to be examined carefully. Identify those where same types in same locations of the block are used with different names. In these cases you can use the => feature of USE to rename those variables. In the module you create for these commons, for each variable create a new name that is not used by any of your procedures. e.g. was_X_or_X1 Then on the USE statement point the appropriate local name to the synthetic name. Note, this is a temporary step and you can cleanup the names later. Test the program.

6) what you have left in the list of commons will take very careful steps in making any changes. Perform incrementally, testing after each change.

Note on 6), you can keep those COMMONs if need be.

Jim Dempsey

View solution in original post

0 Kudos
11 Replies
Arjen_Markus
Honored Contributor I
1,239 Views

Such spaces are only allowed in fixed-form source files.

You might be able to find the occurrences compiling the sources as if they are free-form. That will probably cause a cascade of other errors and warnings, but it is one way ;).

 

0 Kudos
renaud_egal_r_
Beginner
1,239 Views

That will be a huge work because I have a lot of files, but if that's the only way, I'll deal with it !

Thank you Arjen

0 Kudos
Arjen_Markus
Honored Contributor I
1,239 Views

Not necessarily: you can use the /free option to compile the source files. /free instructs the compiler to regard them as free-form source. Then it is a matter of identifying the right error messages.

An alternative might be to write a small program (in any language that you find suitable) to report instances of spaces in between letters. You would have to filter out things like "subroutine mysub" and "else if", as well as literal strings.

0 Kudos
Steve_Lionel
Honored Contributor III
1,239 Views

What problem are you trying to solve? It's legal to have different named variables in the COMMON blocks in different program units, though it's an extremely poor practice. Spaces (and tabs) in variable names are also legal (in fixed-form source) but not a good idea. 

0 Kudos
renaud_egal_r_
Beginner
1,239 Views

I am trying to reverse-engineer an old software of ours, and yeah I'm aware it's full of very bad practices, and this one is far from being the worst. That's precisely why it needs refactoring.

For that I need to understand what data(variables) are used, and where. Then, I want to replace all COMMONs with a USE MODULE statement, meaning I have to rename COMMON variables with unique name.

SUBROUTINE A
   INTEGER x, y
   COMMON /allovertheplace/ x, y
   x=2*y
END SUBROUTINE A

SUBROUTINE B
   INTEGER x1, y1, z1
   COMMON /allovertheplace/ x1, y1, z1
   x1=y1+z1
END SUBROUTINE B

will become 

SUBROUTINE A
   USE ALLOVERTHEPLACEMOD
   x=2*y
END SUBROUTINE A

SUBROUTINE B
   USE ALLOVERTHEPLACEMOD
   x=y+z
END SUBROUTINE B

MODULE ALLOVERTHEPLACEMOD
   USE ALLOVERTHEPLACEMOD
   INTEGER x, y, z
​END MODULE ALLOVERTHEPLACEMOD

That is maybe not a good way to work, but I have to do this step if I want to understand the whole data structure of my program.

0 Kudos
LRaim
New Contributor I
1,239 Views

Do not hurry in doing things.
A COMMON could be used as a buffer to hold variables of very different kinds. Such a structure (which is not a bad habit but an architectural choice) cannot be replaced by a MODULE. 
You have to change the code step by step: make a 1st small change and test, make a 2nd small change and test, ….
The first thing I will do is to eliminate blank spaces and tabs.
Good trip.

 

 

 

0 Kudos
mecej4
Honored Contributor III
1,239 Views

There are two separate issues here, and I think that it would be best to handle each separately.

Blanks in variable names and keywords are legal only in fixed form source, so the code snippet that you posted in #1 is not legal. Adding six leading spaces would make that code legal, but what matters is the form of your legacy source code. I assume that it is in fixed form. I suggest that you use a capable utility to convert the source code to free form. This process will clean up the code, and get rid of the non-significant spaces (and, possibly, tabs). Tools that can assist with this transformation are ftp://ftp.numerical.rl.ac.uk/pub/MandR/convert.f90, https://jblevins.org/mirror/amiller/to_f90.f90, SPAG from https://www.polyhedron.com, the NAG Fortran compiler with the =polish option, etc.

If you have lots of common blocks, and some of those blocks appear with different variable names in different places, or, worse, if the common block items have different types in different places, you probably have to do most of the conversion by hand. SPAG can take an input text file with a substitution list of variable names and replace those variable names in a number of source files.

 

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,240 Views

Luigi's recommendations in #7 should be followed. The only thing I can add is from experience several years ago in doing this very same thing with 13 projects with 750 files.

1) Use your favorite text processing program, AWK, PYTHON, etc. (I used TECO) to search all files for COMMON blocks and produce an output file containing the COMMON block, together with name and variables declared within. I produced this on a single line for each entry.

2) Sort the output file

3) Locate all commons with same name and identical variable lists for all instances of that name. These are likely safe to move directly into a module. I used MOD_NameThatWasUsedOnCOMMONblock. *** you should not assume that all said variables have same type - so verify. You remove from the list the entries you selected. Replace the COMMON declarations with USE MOD_... (in the appropriate place), then compile and test and verify correctness.

4) Locate all named commons with a single declaration, and do the same as in 3)

5) What you have left in the list (if any) are named commons that map the common block differently. Each instance will have to be examined carefully. Identify those where same types in same locations of the block are used with different names. In these cases you can use the => feature of USE to rename those variables. In the module you create for these commons, for each variable create a new name that is not used by any of your procedures. e.g. was_X_or_X1 Then on the USE statement point the appropriate local name to the synthetic name. Note, this is a temporary step and you can cleanup the names later. Test the program.

6) what you have left in the list of commons will take very careful steps in making any changes. Perform incrementally, testing after each change.

Note on 6), you can keep those COMMONs if need be.

Jim Dempsey

0 Kudos
renaud_egal_r_
Beginner
1,239 Views

Thank you all for your replies, that is great advice ! I'll work step by step in order to ensure that the migration went well. 

Does anyone know if there's a way to write unit tests and/or measure the code coverage of my benchmark cases with IVF on Visual Studio 2015 ?

 

Again, thank you very well for your expertise !

0 Kudos
Arjen_Markus
Honored Contributor I
1,239 Views

There are several frameworks that you can use for unit testing - see http://fortranwiki.org/fortran/show/Unit+testing+frameworks.

I wrote one myself :) - ftnunit - see http://flibs.sf.net

As for code coverage: look in Visual Studio under Tools/Intel Compiler/Code Coverage ...

 

0 Kudos
renaud_egal_r_
Beginner
1,239 Views

Hello all,

I finally found all my spaces&tabs variables, and renamed them as you advised earlier by switching to free files format. That's nicer this way too (more readable)

Then, I also moved (some of) my COMMON into a module, as public variables, and the program seems to be ok with that !

Also, Arjen, you mentionned in #11 a unit testing framework, I didn't take the time to look into it, but I definitely will !

Thanks everyone :)

0 Kudos
Reply