Preserving line numbers when pre-processing Fortran code - fortran

I have inherited a 10K-lines Fortran code that uses fpx3 for pre-processing. At this point I should say that I don't have much Fortran experience, and this is my first time dealing with a code that has a pre-processor.
The code works fine, except that when the pre-processing runs, it creates secondary Fortran files (e.g., main.f90 creates t.main.f90) that do not preserve the total amount of lines. The reason, of course, is that some code is lost when pre-processing (IF-ELSE clauses, pre-proc. directives, etc.).
This would be fine, except that when I get a bug in the code, the line number I get from the bug refers to the pre-compiled code (e.g., t.main.90) instead of the original code.
This isn't a major problem, but for nearly every bug I have to check the line (say, line 80 of t.main.f90) and manually try to find this line in the original (let's say it ends up being line 92 of main.f90). I've tried to find a way around this by telling fpx3 to comment the unused lines instead of throwing them out, but I couldn't find much info on fpx3 online.
What's the best way around this?
P.S.: I don't know if it matters, but I'm using ifort to compile.

Try -fixed as a .f90 file is assumed to be -free (free form), and fixed preserves the 1st few columns and the continuation in column 6.
If the number at on the right hand side, then NOT -132, but -72 or -80. To not include the numbers as "compilable" code. I use -132, so you have to look up the right switch.

Related

ifort dialect options for very old code

I have been suddenly given a few very old fortran codes to compile and get working for my research group. Using ifort when I compile the code I get the following error:error #6526: A branch to a do-term-shared-stmt has occurred from outside the range of the corresponding inner-shared-do-construct.
Here is the bit of code that seems to be at fault:
...
IF(THRU.GT.0.D0) GO TO 120 00011900
L1=LL 00012000
A1=AA 00012100
DR1=DRR 00012200
RMAX1=RMAXX 00012300
RMIN1=RMINN 00012400
IF(DR1.EQ.0.D0) DR1=DRP 00012500
KMAX1=(RMAX1-RMIN1)/DR1+1.D-08 00012600
IF(KMAX1.GT.NN .OR. KMAX1.LE.0) KMAX1=NN 00012700
RINT1=RMAX1 00012800
IF(RMAX1.NE.0.D0) 00012900
2RMAX1=DR1*DFLOAT(KMAX1)+RMIN1 00013000
IUP=KMAX1 00013100
R=RMIN1 00013200
DO 120 K1=1,KMAX1 00013300
R=R+DR1 00013400
XX(K1)=R 00013500
120 CONTINUE 00013600
WRITE(IW,940) NAM1,IOPT1,L1,A1,DR1,RMAX1,RMIN1,ANU1,BNU1,CNU1 00013700
121 CONTINUE 00013800
...
Being quite unfamiliar with fortran I have been doing some searching and what I can see is that it does not like that IF statement branching to the terminal statement of the DO loop. Also, it seems that some older dialects or compilers supported this.
My questions is this: Is there an option that will allow ifort to successfully compile this? I.E. Is there a specific dialect compatibility option on ifort that will make this legal?
What are the side effects of that particular code on a compiler that would accept it? Is it possible that aside from the write statement the side effects are identical to going to line 121? Or was maybe the do loop supposed to go to 121?
I would consider modifying the code if not for the fact that my advisor told me that I should not make any changes whatsoever without consulting him first and so I ask this question to see if I need to consult him or not. That said if my only option is a modification to the code suggestions would be welcome for that so that I can have an idea of what needs to be done when I go to my advisor.
I'll note that the code in question isn't valid even as Fortran 77, but people did weird stuff back in the mists of time. I'll defer to any historian or person with experience. In particular, one should be very careful to understand any subtleties in the code in relation to my "answer" here.
If we assume that the intention of the goto given is to jump to code after the execution of the loop, then I answer about minimal change to the code.
Stripping line-number comments for clarity then
DO 120 K1=1,KMAX1
R=R+DR1
XX(K1)=R
120 CONTINUE
WRITE(IW,940) NAM1,IOPT1,L1,A1,DR1,RMAX1,RMIN1,ANU1,BNU1,CNU1
can be replaced by
DO K1=1,KMAX1
R=R+DR1
XX(K1)=R
END DO
120 WRITE(IW,940) NAM1,IOPT1,L1,A1,DR1,RMAX1,RMIN1,ANU1,BNU1,CNU1
I would be quite surpised if the author of the code intended the loop to continue to 121: no variable referenced by the write statement is updated in the loop. It is possible that the goto was intended to reference 121 but I do see that many variables are not updated in the section that would be skipped.

Compiler run-time error reporting with location of error

I'm writing a compiler in C++ (Ubuntu 12.04. with gcc). So far, cumulative error/warning reporting with fairly precise line and column number of error/warning location works fine.  
My project goals include simply learning how to do this, so I'm adding a preprocessing stage (in a first step doing only minimal stuff like string concatenation, comment removal, etc), creating a resulting tmp file. It will not be necessary at this point as I could concatenate strings in my lexer while parsing, and the lexer already handles comments fine, but I'd like to understand how to handle it efficiently and as elegantly as I can. 
Compile time errors are not hard:   
(1) do error check (-> report compile-time errors)
(2) if no errors, preprocess -> tmp file
(3) run parser, etc., on tmp file (which is compile-time error free)
However, I also report run-time errors with line number (eg, for array out of bounds checks for arrays with integer expression bounds). As the error checks will be added to the byte code of my IR when parsing the tmp file only, and this file can significantly differ from the source file (in particular if we start allowing the pasting in of header files, say), how on earth can you reasonably report helpful error location? Is there a standard trick how gcc, say, handles this? The type of bound check mentioned of course doesn't happen for C; but runtime error reporting applies to, say, dynamic resolution of pointers in a hierarchy in C++, and gcc gets the line numbers just fine.
You can record line number information in your temporary file produced by your preprocessor, such as Line Control of cpp.
The C preprocessor informs the C compiler of the location in your source code where each token came from. Presently, this is just the file name and line number.

How do c/c++ compilers know which line an error is on

There is probably a very obvious answer to this, but I was wondering how the compiler knows which line of code my error is on. In some cases it even knows the column.
The only way I can think to do this is to tokenize the input string into a 2D array. This would store [lines][tokens].
C/C++ could be tokenized into 1 long 1D array which would probably be more efficient. I am wondering what the usual parsing method would be that would keep line information.
actually most of it is covered in the dragon book.
Compilers do Lexing/Parsing i.e.: transforming the source code into a tree representation.
When doing so each keyword variable etc. is associated with a line and column number.
However during parsing the exact origin of the failure might get lost and the information might be off.
This is the first step in the long, complicated path towards "Engineering a Compiler" or Compilers Theory
The short answer to that is: there's a module called "front-end" that usually takes care of many phases:
Scanning
Parsing
IR generator
IR optimizer ...
The structure isn't fixed so each compiler will have its own set of modules but more or less the steps involved in the front-end processing are
Scanning - maps character streams into words (also ignores whitespaces/comments) or tokens
Parsing - this is where syntax and (some) semantic analysis take place and where syntax errors are reported
To make this up to you: the compiler knows the location of your error because when something doesn't fit into a structure called "abstract syntax tree" (i.e. it cannot be constructed) or doesn't follow any of the syntax-directed translation rules, well.. there's something wrong and the compiler indicates the location where this didn't happen. If there's a grammar error on just one word/token then even a precise column location can be returned since nothing matched a terminal keyword: a basic token like the if keyword in the C/C++ language.
If you want to know more about this topic my suggestion is to start with the classic academic approach of the "Compiler Book" or "Dragon Book" and then, later on, possibly study an open-source front-end like Clang

PGI Fortran integer format

I have an input text file that contains an integer record like:
1
which is read in Fortran code as:
read(iunit,'(i4)') int_var
which works fine with Gfortran, but the same code compiled with PGI Fortran Compiler expects a field 4 characters wide (the actual record is just 1 character) and throws an error. Now I know that the format specifies the width and this may or may not be correct behavior according to the Fortran standard, but my question is - is there a compiler option for PGI that would make it behave like Gfortran in this respect?
This 3rd party code I'm using has a lot (hundreds or thousands) of read statements like this and input data has a lot of records with "wrong" width so both modifying the code or the input data would require significant effort.
I don't think this is connected to blank. This read should not cause an error, unless you opened the file iunit with pad="no". Default is allways pad="yes", which causes the input record to be padded with blanks, if it is too short.
Are you sure, that you use correct input files, with correct line ends? There could be problems with text file that originate in Windows and in Unix the CR could be read in the input record. In this case using the unix2dos utility might help. You may try to read a character(4) string using the a4 edit descriptor to test for this.
Does PGI Fortran support the open keyword blank="null"? I think that this will change the read to the behavior that you want and minimize the modifications to the code. blank="null" versus blank="zero" doesn't seem to make a difference in gfortran 4.7.

How do I associate changed lines with functions in a git repository of C code?

I'm attempting to construct a “heatmap” from a multi-year history stored in a git repository where the unit of granularity is individual functions. Functions should grow hotter as they change more times, more frequently, and with more non-blank lines changed.
As a start, I examined the output of
git log --patch -M --find-renames --find-copies-harder --function-context -- *.c
I looked at using Language.C from Hackage, but it seems to want a complete translation unit—expanded headers and all—rather being able to cope with a source fragment.
The --function-context option is new since version 1.7.8. The foundation of the implementation in v1.7.9.4 is a regex:
PATTERNS("cpp",
/* Jump targets or access declarations */
"!^[ \t]*[A-Za-z_][A-Za-z_0-9]*:.*$\n"
/* C/++ functions/methods at top level */
"^([A-Za-z_][A-Za-z_0-9]*([ \t*]+[A-Za-z_][A-Za-z_0-9]*([ \t]*::[ \t]*[^[:space:]]+)?){1,}[ \t]*\\([^;]*)$\n"
/* compound type at top level */
"^((struct|class|enum)[^;]*)$",
/* -- */
"[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
This seems to recognize boundaries reasonably well but doesn’t always leave the function as the first line of the diff hunk, e.g., with #include directives at the top or with a hunk that contains multiple function definitions. An option to tell diff to emit separate hunks for each function changed would be really useful.
This isn’t safety-critical, so I can tolerate some misses. Does that mean I likely have Zawinski’s “two problems”?
I realise this suggestion is a bit tangential, but it may help in order to clarify and rank requirements. This would work for C or C++ ...
Instead of trying to find text blocks which are functions and comparing them, use the compiler to make binary blocks. Specifically, for every C/C++ source file in a change set, compile it to an object. Then use the object code as a basis for comparisons.
This might not be feasible for you, but IIRC there is an option on gcc to compile so that each function is compiled to an 'independent chunk' within the generated object code file. The linker can pull each 'chunk' into a program. (It is getting pretty late here, so I will look this up in the morning, if you are interested in the idea. )
So, assuming we can do this, you'll have lots of functions defined by chunks of binary code, so a simple 'heat' comparison is 'how much longer or shorter is the code between versions for any function?'
I am also thinking it might be practical to use objdump to reconstitute the assembler for the functions. I might use some regular expressions at this stage to trim off the register names, so that changes to register allocation don't cause too many false positive (changes).
I might even try to sort the assembler instructions in the function bodies, and diff them to get a pattern of "removed" vs "added" between two function implementations. This would give a measure of change which is pretty much independent of layout, and even somewhat independent of the order of some of the source.
So it might be interesting to see if two alternative implementations of the same function (i.e. from different a change set) are the same instructions :-)
This approach should also work for C++ because all names have been appropriately mangled, which should guarantee the same functions are being compared.
So, the regular expressions might be kept very simple :-)
Assuming all of this is straightforward, what might this approach fail to give you?
Side Note: This basic strategy could work for any language which targets machine code, as well as VM instruction sets like the Java VM Bytecode, .NET CLR code, etc too.
It might be worth considering building a simple parser, using one of the common tools, rather than just using regular expressions. Clearly it is better to choose something you are familiar with, or which your organisation already uses.
For this problem, a parser doesn't actually need to validate the code (I assume it is valid when it is checked in), and it doesn't need to understand the code, so it might be quite dumb.
It might throw away comments (retaining new lines), ignore the contents of text strings, and treat program text in a very simple way. It mainly needs to keep track of balanced '{' '}', balanced '(' ')' and all the other valid program text is just individual tokens which can be passed 'straight through'.
It's output might be a separate file/function to make tracking easier.
If the language is C or C++, and the developers are reasonably disciplined, they might never use 'non-syntactic macros'. If that is the case, then the files don't need to be preprocessed.
Then a parser is mostly just looking for a the function name (an identifier) at file scope followed by ( parameter-list ) { ... code ... }
I'd SWAG it would be a few days work using yacc & lex / flex & bison, and it might be so simple that their is no need for the parser generator.
If the code is Java, then ANTLR is a possible, and I think there was a simple Java parser example.
If Haskell is your focus, their may be student projects published which have made a reasonable stab at a parser.