Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!uwm.edu!cs.utexas.edu!rutgers!cmcl2!lanl!jlg From: jlg@lanl.gov (Jim Giles) Newsgroups: comp.lang.fortran Subject: Re: Fortran 77 Style Guide (long, REPOST) Message-ID: <59012@lanl.gov> Date: 3 Aug 90 02:07:18 GMT References: <26B89BE1.4349@ics.uci.edu> Organization: Los Alamos Natl Lab, Los Alamos, N.M. Lines: 200 This is not a disagreement with the style guide David Levine gave but merely a commentary on it. I say this because I will only discuss those parts of his submission that I disagree with. As a result, I might be mistaken for a dissenter. In fact, as will be seen, I don't discuss most of what he says (and I therefore agree with those parts). From article <26B89BE1.4349@ics.uci.edu>, by levine@crimee.ics.uci.edu (David Levine): > [...] > a) In addition to the standard character set (where the notation [0-9] > indicates the numerals 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9) > space $ ' ( ) * + , - . / : = [0-9] [A-Z] > the following characters may be used: > ! # & [a-z] Believe it or not, there are still implementations without these characters (or, at least, compilers which still don't recognize them). You can use these as long as you have access to some tool to remove or replace them when you need to (this may be never - so maybe you're safe). > b) Identifier names may be up to 31 characters long (the first 6 > remain significant). _NEVER_ use more characters in an identifier than the compiler considers significant. _NEVER_ buy a compiler which allows an identifier to contain insignificant characters. Yes, the 6 character limit of standard Fortran is irritating. Tricking yourself with identifiers that _look_ different to you, but might not be to the compiler is _not_ a good solution. > c) INCLUDE statements may be used. Well, just don't count on the _compiler_ to do it. Many compilers don't. Any half-way acceptable text editor ought to have sufficient macro definition capability to expand the INCLUDE. > d) INTEGER*4 may be used when INTEGER defaults to 2 bytes. Not available everywhere. Just like the lower case letters, you should only use this if you have an automatic tool to remove them - otherwise you got to do it by hand. > 2) Avoid compiler directives in code, especially if an equivalent > compiler option is available. If the directives in code do the same thing that command line directives do, there's no reason for the vendor to supply both. You can't make rigid rules about this issue without assuming things that you don't know about what the directives might do and what the priorities of the programmers are. > 3) The first two letters of the routine and file name correspond to the > module and the remaining four uniquely identify the routine. > Additional characters may be used to create a more sensible name. See above for comments on insignificant identifier characters. > VI. Statement labels > 1) Assign a label only if necessary. > 2) Assign labels in ascending order. My only complaint here is wording. In Fortran, the word "ASSIGN" has a specific meaning which isn't intended here. Replace "assign" with "declare" in all the stuff above, and I'll agree with it. > 3) Assign a separate sequence of labels to FORMAT labels that are grouped > at the end of a subprogram. Same comment about "assign" plus the following: whenever possible, put the format into the I/O statement which uses it. Use labeled formats only when several I/O statements share the same (long) format. > VII. Capitalization > 1) Set keywords in all caps. > 2) Set symbolic names of constants (parameters) in all lower case. > 3) Set all other identifiers in initial caps with embedded words initial > capped. Way too rigid. In a language like C, where case is significant, such rigid rules are important in order to share code among users (or across time). In Fortran, case should be used freely (with comments) for emphasis and documentation. > VIII. Spacing > [...] > 3) Do not put space between and array name and its index, Array(I). > 4) Put one space between a subprogram name and its argument list, e.g., > Subr (Arg1, Arg2). > 5) Except in argument lists, put a space after an open parenthesis and > before a close parenthesis. > 6) Put one space between arguments. > [...] > 8) Use indentation to reinforce control flow; each indent is 3 columns. > [...] Again too rigid. Spaces should be used to enhance legibility, not to conform to some rigid style rules. All these things, but particularly how many columns to indent, should be up to the individual programmer. Any other decision doesn't allow for the different constraints of different applications and users. As long as a program uses space in a reasonably consistent way, it doesn't matter what the particular rules are. > 2) Limit to 31 characters; distinguish with first 6. Again, _NEVER_ use an identifier with more characters that are significant. > 1) Use PARAMETERs to symbolically name all compile-time constants. A little to rigid. If the constant is something that's likely to change in future versions of the code, name it. If the constant is hard to remember (or long and prone to typing errors), then name it. Otherwise don't name it. I've seen people who've named 1 (one), and then used that everywhere - this doesn't enhance legibility or maintainability at all. > XI. Typing > [...] > INTEGER*4 Not universally available. > [...] > 4) Declare all variables. Use a compiler option to ensure declaration. > If no such compiler option is available, setting the implicit type of > all variables to a type that is not used in the program often snags > undeclared variables. An example is: IMPLICIT COMPLEX*16 A-Z. A better 'snag' is IMPLICIT LOGICAL A-Z. Complex has the disadvantage that arithmetic (the most common variable use) is still legal on it. Logical is better because it is legal in fewer contexts. > XII. Operators > [...] > 3) Compare unequal length character strings with LGE, LGT, LLE, and LLT. Compare _all_ character strings this way. Otherwise you get a non-portable lexicographic ordering from some machines. > XIII. Expressions > [...] > 2) Split an expression across lines after an operator. Obviously, only if the line _needs_ splitting :-). > XIV. Arrays > 1) Declare array dimensions in the type declaration rather than in a > separate DIMENSION statement. In fact, _never_ use the DIMENSION statement. Means the same thing, I just like it stated a clearly as possible. > 3) Preferably operate on arrays such that the first indices vary fastest > and the last vary slowest. An important issue in bygone days and still an optimization isse on scalar machines with small caches. This isn't a disagreement, but I'd like to point out that there are other orders which might be desireable. For example, on a vector machine, you want the index with the longest dimension to be on the inner loop (longer vectors). > XVII. COMMON blocks > [...] > 3) SAVE all COMMON blocks. I've requested the Fortran committee for years to make SAVE the default for COMMON. > 6) Initialize COMMON blocks only in BLOCK DATA subprograms. In spite of the fact that the standard calls for this, I am not sure that I agree. If MODULES existed, the obvious preferred place to initialize globals would be in the MODULE. But, for COMMON, I think BLOCK DATA was always a clumbsy solution. Anyway, _wherever_ you do it, you _should_ initialize _all_ common data. > 7) Compile BLOCK DATA subprograms with another program unit in which it > is referred to with an EXTERNAL statement. This is why I'm not sure I agree with using BLOCK DATA at all. > XVIII. Input/Output > 2) Position a FORMAT statement immediately following its reference. Position formats _in_ the I/O statement that refer to them if possible. > APPENDIX I. Loop Constructs > 2) while > 10 CONTINUE > . . . > IF ( condition ) GOTO 20 > . . . > GOTO 10 > 20 CONTINUE If it's _really_ a while construct, there should _NEVER_ be any code between the beginning of the loop and the test. This more strongly resembles an infinite loop with an exit condition buried in the middle. J. Giles