Problem with COMMON

Problem with COMMON

My code is old and is using lots of variables in different places to holdfile names.
At present all these variables are dimensioned to 80.
I want to increase this to say 255.
Therefore to make it supportable in the future I want to define one varialbe, say FileNameLength as 255.

integer,parameter:: FileNameLength=250
character*(FileNameLength) cFileName

This works OK on its own, but I get problems with duplicate definitions with 'COMMON' satements which are used to dimension many of the variables.

What is the solution to this?

Thanks,
David

14 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

I don't quite understand the nature of the problem. There's nothing wrong with what you have shown so far. Can you show a self-contained example that demonstrates the problem?

Steve - Intel Developer Support

Perhaps you are including several header files some of which may declare the same common block but with different/different allocations of variables?

Also your given declaration for cFileName is not in a COMMON.

Jim Dempsey

The problem is that I have FileNameLength defined in a common block AND in the program.

The program has

include 'fnames.gcb'

integer,parameter:: FileNameLength=250
character*(FileNameLength) cFileName

etc...

The common block is in file 'Fnames.gcb'

integer,parameter:: FileNameLength=250
character*(FileNameLength) cgbf,CCOD
common/fnames/ cgbf,CCOD

The error message is:

This name has already been assigned a data type. [FILENAMELENGTH]

as FileNameLength is defined both in the program & in the common block.
I have triedFileNameLength in a Module and using USE.
There must be a simple way of defining a variable that I can use in the program and in a common block.

Hope this helps,
David

FileNameLength isn't a variable - you have declared it as a PARAMETER value and are attempting to assign a value to it twice.

Also make sure you aren't mixing up 250 and 255 for your name lengths

More simply, you are declaring the name FileNameLength twice, which is not allowed. Remove one of the definitions.

Steve - Intel Developer Support

I want to use the variable 'FileNameLength' in several Common blocks.

I have tried removing them, to leave only one, but get the error messages:

'A COMMON block data object must not be an automatic object.'

and

'This name has not been given an explicit type. [FILENAMELENGTH]'

I'm getting confused,

David

The best way to do it is to have it in the include file (just as you have it now) and ONLY include the file wherever the symbols are needed. You appear to have a mixture of include and re-spelling of definitions.

Jugoslav

Jugoslav
www.xeffort.com

I'm not sure if I follow you.

I have made a new common block called fnl.gcb:

integer:: FileNameLength=250
common/FNL/FileNameLength

It wouldn't compile with 'Parameter'.

Then in each program that needs this variable or has an include file that needs this variable I have added include 'fnl.gcb'.

When I compile, I get an error on the first program which containsa common block.

Error: A COMMON block data object must not be an automatic object.

I don't know what that error messagemeans.

I don't think I have any spelling problems.

David

Your first version of .gcb file was perfectly fine. This one won't work -- you need a PARAMETER to declare length of a character within the common block (that's what compiler tells you that "COMMON block data object must not be an automatic object"), and you can't put a parameter within a common block, because it's not a variable.

Your original problem was that you defined FileNameLength twice, once in .gcb file and other time again in code (.for file) (that's what I meant by "spelled"). The solution was just to remove the re-declarations.

Jugoslav

Jugoslav
www.xeffort.com

David,

If you can, why not dispense with COMMON. You can do this by creating a module containing the arrays, variables and constant parameters. I've done this on a Solution with 11 project files and ~700 source modules. It is a bit of work but you can do it incrimentaly. You could start with

-----------------------------

! mod_common.f90
module mod_common

integer,parameter:: FileNameLength=250
character*(FileNameLength) cFileName
end module mod_common
-----------------------

Then insert "use mod_common" at the top of the routines that use FileNameLength or cFileName.

Then as you find more items that you would like better control over you can place them in there too.

You will find that this is a relatively easy way to convert a fixed dimension array in COMMON to an allocatable array. No source code changes other than for the COMMON/mod_common, the use mod_common, and the allocation in the init code. All array references remain untouched.

Jim Dempsey

I have created the module fnl:

Module fnl
! file name length
integer,parameter:: FileNameLength=250
end module

Then added 'use fnl' to any procedures that require it.

The common blocks defining the variable just then need:
character*(FileNameLength) cgbf

I think that's it sorted, thanks.
David

Keep in mind that you can start placing more features into the module section. Converting an array from fixed size in common to allocatable in the module is relatively easy to do (once you insert the "use foo"). Also it makes for easier code maintenance. Especialy when you compile one set of subroutines with one set of includes with COMMONs and a different set of subroutimes with a different set of includes with COMMONs only to find during debugging that the common COMMONs aren't quite the same. Using modules forces a singular instance of a formerly named variable in COMMON.

One of the steps along the learning curve to using modules is often the include files for COMMON use EQUIVELENCE.. To overcome this use UNION

COMMON Array, Array1
DIMENSION Array(10,10), Array1(100)
EQUIVELENCE (Array(1,1) Array1(1))

becomes

union
map
real :: Array(10,10)
end map
map
real :: Array1(100)
end map
end union

Then as you progress through your changes that some routines may have a common array(10,10) and others use the same name but different extents or rank. To easily overcome this use a derrived type and use the Fortran Preprocessor with #define.

module foo
...
type badabing

union
map
real :: Array(10,10)
end map
map
real :: Array1(100)
end map
end union
end type badabing

type badabang

union
map
real :: Array(10,10)
end map
map
real :: Array1(100)
end map
end union
end type badabang

type(badabing) :: bing
type(badabang) :: bang
end module foo

Then in the include files that are used in the souce files that require the badabing have

#define Array badabing.Array
#define Array1 badaging.Array1

That is it. No souce code changes to differentiate the references. You do have to select the appropriate #define but that is easier and less error prone that search and replace.

Jim Dempsey

oops us

#define Array bing.Array

#define Array1 bing.Array1

Leave a Comment

Please sign in to add a comment. Not a member? Join today