I'm trying to compile a huge, world-renowned numerical weather prediction code - written mostly in Fortran 90 - that uses cpp extensively, and successfully, with PGI, Intel and gfortran. Now, I've inherited a version where experts have added several hundred cases of variadic macros. They use Intel and fpp, which is presumably a little more Fortran-centric, and can get it all to work. I need to use gfortran, and have not been able to get cpp to work on this code with its new additions.
A gross simplification of the problem is as follows -
Code to preprocess:
PRINT *, "Hello" // "Don"
#define adderv(...) (myadd(__VA_ARGS__))
sumv = adderv(1, 2, 3, 4, 5)
Using cpp without the -traditional option will handle the variadic macro, but not the Fortran concatenation:
$ cpp -P t.F90
PRINT *, "Hello"
sumv = (myadd(1, 2, 3, 4, 5))
On the other hand, using the -traditional flag handles the concatenation, but not the variadic macro:
$ cpp -P -traditional t.F90
t.F90:2:0: error: syntax error in macro parameter list
#define adderv(...) (myadd(__VA_ARGS__))
^
PRINT *, "Hello" // "Don"
sumv = adderv(1, 2, 3, 4, 5)
I'm really struggling to find a way to facilitate the processing of both.
I've started by playing with gpp, and feel like I'm getting close, but the reality is I might still be a long way from a solution. It doesn't accept the ... and, it doesn't expand __VA_ARGS__. Of course, the following isn't really a variadic macro any more...
PRINT *, "Hello" // "Don"
#define adderv() (myadd(__VA_ARGS__))
sumv = adderv(1, 2, 3, 4, 5)
$ gpp t.F90
PRINT *, "Hello" // "Don"
sumv = (myadd(__VA_ARGS__))
I've scoured the web to no avail, and the best possibility I've seen so far, which strikes me as possibly ugly and painful, is to split all my Fortran concatenation operators into separate lines. i.e.
PRINT *, "Hello" // "Don"
becomes
PRINT *, "Hello" /&
& / "Don"
The innards of cpp and gpp are a bit intimidating to me, but if anybody sees the potential for success and might point me in the right direction, I'd be very appreciative. Restructuring this huge code really isn't an option, though an automated strategy (such as splitting those concat operators into separate lines) might be, if I'm desperate enough.
Additional information - roygvib suggested I try adding the -C flag. We had been suppressing it lately because it seemed to introduce many C comments into the Fortran code. Well, I went ahead and tried this, and I think I'm closer:
$ cat t.f90
PRINT *, "Hello" // "Don"
#define adderv(...) (myadd(__VA_ARGS__))
sumv = adderv(1, 2, 3, 4, 5)
When I invoke with -P and -C flags, naturally it passes through the C++ (Fortran concat operator), but it also seems to generate some C-commented copyright text:
$ /lib/cpp -P -C t.F90
/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
.
.
.
/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / Unicode 6.0. */
/* We do not support C11 <threads.h>. */
PRINT *, "Hello" // "Don"
sumv = (myadd(1, 2, 3, 4, 5))
A little bit of research ( Remove the comments generated by cpp ) is suggesting that this addition of the copyright may be a relatively new "feature" of cpp.
I can't see any simple way to suppress this, so I'm thinking I may need to build a wrapper script (e.g. mycpp) that calls cpp as above, filters out any C-style comments, then passes that to the next stage.
It's not optimal, and I'm a little leery because this whole package also has C code in it. Theoretically, though, I think that the worst thing that would happen would be failure to generate comments in preprocessed C code.
If anybody has knowledge as to how I might simply suppress the generation of that copyright message, I might be in business.
At least in the context of the simple example described below, I resolved the problem by installing an older cpp. Other research had confirmed that version 4.8 was inserting additional C comments into preprocessed Fortran code, which obviously isn't a good thing. The solution was simple, use cpp-4.7.
Installation (on Ubuntu 16.04) was more straightforward than I had anticipated. A simple
sudo apt-get install cpp-4.7
put the necessary executable in /usr/bin/cpp-4.7
and that preprocesses the following examples the way I want.
$ /usr/bin/cpp-4.7 -C -P t.F90
PRINT *, "Hello" // "Don"
sum = (myadd(1, 2, 3, 4, 5))
Like DonMorton, I am trying to use cpp -P with fortran files because __VA_ARGS__ and others things are used. As without -C option // are removed and comments are added.
So, I removed these extralines using the ideas of another answer :
cpp -P -C t.F90 | sed '/\/\*.*\*\// d; /\/\*/,/\*\// d'
And, I get, as expected :
PRINT *, "Hello" // "Don"
sumv = (myadd(1, 2, 3, 4, 5))
But, there is still a problem. You could not use // (C++ style comments) in macro args : // something is replaced by /* something */
Related
I have a file that generates cc code using flex. When I use the version 2.5.4a-10 the codes works as expected.
If I use bit more recent version 2.5.37 or even newer like 2.6 the generated code seems not to allocate anything. It uses some pointers defined with nullptr and crashes.
I think the syntax has changed in between these versions. I find it also strange that Debian/Ubuntu have a package called flex-old saying:
flex is a tool for generating scanners: programs which recognize lexical
patterns in text. This is the old 2.5.4a version, which is no longer
being developed. You should normally choose flex, unless you have
legacy lexer files that do not work with a modern flex.
This product includes software developed by the University of California,
Berkeley and its contributors. The upstream source code can be found at
http://flex.sourceforge.net/
(Editor's note: Flex has moved to Github but v2.5.4a is not there.)
That version seems to be a big deal for others I suspect. Getting to my question:
Is there any manual or guide of what I have to do in order to port that code to generate some c++ code that works in more recent versions of flex?
EDIT: Here is my simple example taken from something larger:
int num_lines = 0, num_chars = 0;
%%
\n ++num_lines; ++num_chars;
. ++num_chars;
%%
int main()
{
yy_init=1;
yylex();
printf( "# of lines = %d, # of chars = %d\n",
num_lines, num_chars );
return 0;
}
flex it with flex file.l and build it with gcc lex.yy.c -lfl. Now, if you used version 2.5.4 it will work. With later versions it translates and compiles just fine, but when you run the program you will get segmentation fault.
I found the problem myself. The variable yy_init can be explicitly set in that old version. In newer versions it is not allowed. I'm not sure if that is intended, maybe someone can explain why this behavior is observed. I find it a bit strange.
If someone has a similar problem, you might want to take a look at the yy_init variable. Other than that I had no issues.
This one's going to take a bit of explaining. Please bear with me.
What I Have
I have in my possession some Fortran source code and some binaries that have been compiled from that code. I did not do the compilation, but there is a build script that suggests G77 was used to do it.
As well as the Fortran stuff, there is also some Java code that provides users with a GUI "wrapper" around the binaries. It passes information between itself and the binaries via their input/output/error pipes. The Java code is very messy, and this way of doing things adds a lot of boilerplate and redundancy, but it does the job and I know it works.
What I Need
Unfortunately, I'd like to make some changes:
I want to create a new Python wrapper for the binaries (or, more precisely, extend an existing Python program to become the new wrapper).
I want to be able to compile the Fortran code as part of this existing program's build process. I would like to use gfortran for this, since MinGW is used elsewhere in the build and so it will be readily available.
The Problem
When I compile the Fortran code myself using gfortran, I cannot get the resulting binaries to "talk" to either the current Java wrapper or my new Python wrapper.
Here are the various ways of printing to the console that I have tried in the Fortran code:
subroutine printA(message)
write(6,*) message
end
subroutine printB(message)
write(*,*) message
end
subroutine printC(message)
use iso_fortran_env
write(output_unit,*) message
end
There are also read commands as well, but the code doesn't even get a change to execute that part so I'm not worrying about it yet.
Extra Info
I have to call gfortran with the -ffixed-line-length-132 flag so that the code compiles, but apart from that I don't use anything else. I have tried using the -ff2c flag in the vague hope that it will make a difference. It doesn't.
This stackoverflow post is informative, but doesn't offer me anything that works.
The relavant manual page suggests that printA should work just fine.
I'm working on Windows, but will need this to be multi-platform.
Juse in case you're intested, the Java code uses Runtime.getRuntime().exec("prog.exe") to call the binaries and then the various "stream" methods of the resulting Process object to communicate with them. The Python code uses equivalents of this provided by the Popen object of the subprocess module.
I should also say that I am aware there are alternatives. Rewriting the code in Python (or something else like C++), or making amendments so that is it can be called via F2Py have been ruled out as options. Using g77 is also a no-go; we have enough dependencies as it is. I'd like to be able to write to / read from the console properly with gfortran, or know that it's just not possible.
Hard to say without seeing more details from your Fortran and Python codes. The following pair of code works for me (at least under Linux):
Fortran program repeating its input line by line prefixed with line number:
program test_communication
use iso_fortran_env, stdout => output_unit, stdin => input_unit
implicit none
character(100) :: buffer
integer :: ii
ii = 1
do while (.true.)
read(stdin, *) buffer
write(stdout, "(I0,A,A)") ii, "|", trim(buffer)
flush(stdout)
ii = ii + 1
end do
end program test_communication
Python program invoking the Fortran binary. You can feed it with arbitrary strings from the console.
import subprocess as sub
print "Starting child"
proc = sub.Popen("./a.out", stdin=sub.PIPE, stdout=sub.PIPE)
while True:
send = raw_input("Enter a string: ")
if not send:
print "Exiting loop"
break
proc.stdin.write(send)
proc.stdin.write("\n")
proc.stdin.flush()
print "Sent:", send
recv = proc.stdout.readline()
print "Received:", recv.rstrip()
print "Killing child"
proc.kill()
I am a novice c++ programmer so please forgive me if this is a naive question. I have files containing large arrays holding tens-of-thousands of strings that I have used previously in javascript applications. Is there some way to include these into C++ source code so that the arrays are compiled along with the code?
At present, the files are formatted as functions that return (javascript) literal arrays, like this:
// javascript array stored in .js text file
function returnMyArray()
{
return ["string1", "string2", "string3", ... "stringBigNumber"];
} // eof returnMyArray()
I 'include' the external file with the usual javascript script & src tags and assign the array with something like:
myArray = returnMyArray();
I want to achieve the equivalent in c++, i.e. assign an array stored in a file to an array in my c++ source code so that the data is available for execution when compiled.
I suppose in theory I could copy and paste (suitable formatted) arrays from files into my c++ source code but they are too large for this to be practical.
I can easily re-write the files to whatever format would be easiest to have c++ access the data - either in c++ array syntax or one string per line to be read into an array.
In a similar vein, is there an easy way to include files containing custom function libraries when compiling with g++ in terminal? (my web searches show plenty of ways for various IDE applications but I am writing source in vim and compiling with g++ on the command line).
I am sorry if this is trivial and I have missed it but I am stumped!
Thank you.
Here's how I'd structure this:
file: data.array
/* C++ style comments are ok in this file and will be ignored
* both single and multiline comments will work */
// the data in the array is a comma seperated list, lines can be any length
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
// more comma seperated data
9996, 9997, 9998, 9999
file: class.h
extern int myArray[]; // you should fill in the size if you can
// more stuff here
file: class.cpp
// if you have an editor that highlights syntax and errors, it may not like this
// however, #include is handled before compiling and performs a blind substitution
// so this is perfectly legal and should compile.
// Visual C++ 2010 highlights this as an error, but the project builds fine.
int myArray[]
{
#include "data.array"
};
// other definitions of stuff in class.h
I was looking at frama-c as a way to process C header files in OCaml (e.g. for generating language bindings). It's attractive because it seems like a very well-documented and maintained project. However, after a lot of googling and searching through the documentation, I can't find anything suitable for the purpose. Am I just missing the right way to do this, or is it outside the scope of frama-c? It seems like a fairly trivial thing for it to do, compared to some of the other plugins.
As Pascal said, I don't think that it is possible from the command line, but because you will have to write some code anyway, you can set the flag Rmtmps.keepUnused. This is a script that you can use to see the declarations :
let main () =
Rmtmps.keepUnused := true;
let file = File.from_filename "t.h" in
let () = File.init_from_c_files [ file ] in
let _ast = Ast.get () in
let show_function f =
let name = Kernel_function.get_name f in
if not (Cil.Builtin_functions.mem name) then
Format.printf "Function #[<2>%a:# #[#[type: %a#]# #[%s at %a#]#]#]#."
Kernel_function.pretty f
Cil_datatype.Typ.pretty (Kernel_function.get_type f)
(if Kernel_function.is_definition f then "defined" else "declared")
Cil.d_loc (Kernel_function.get_location f)
in Globals.Functions.iter show_function
let () = Db.Main.extend main
To run it, you have to use the -load-script option like this :
$ frama-c -load-script script.ml
Developing a plug-in will be more appropriate for more complex processing (see the Developer Manual for that), but a script make it easy to test.
In the current state, I would say that it is unfortunately impossible to use Frama-C to parse declarations of functions that are neither defined or used.
t.h:
int mybinding (int x, int y);
This gives you a view of the normalized AST. Normalized means that everything that could be simplified was:
$ frama-c -print t.h
[kernel] preprocessing with "gcc -C -E -I. t.h"
/* Generated by Frama-C */
And unfortunately, since mybinding was neither used nor defined, it was erased.
There is an option to keep declarations with specifications, but what you want is an option to keep all declarations. I have never noticed such an option:
$ frama-c -kernel-help
...
-keep-unused-specified-functions keep specified-but-unused functions (set by
default, opposite option is
-remove-unused-specified-functions)
And the option to keep functions with specifications does not do what you want:
$ frama-c -keep-unused-specified-functions -print t.h
[kernel] preprocessing with "gcc -C -E -I. t.h"
/* Generated by Frama-C */
Say I have an executable (running on mac, win, and linux)
a.out [-a] [-b] [-r -i <file> -o <file> -t <double> -n <int> ]
where an argument in [ ] means that it is optional. However, if the last argument -r is set then -i,-o,-t, and -n have to be supplied, too.
There are lots of good C++-libraries out there to parse command-line arguments, e.g. gflags (http://code.google.com/p/gflags/), tclap (http://tclap.sourceforge.net/), simpleopt(http://code.jellycan.com/simpleopt/), boost.program_options (http://www.boost.org/doc/libs/1_52_0/doc/html/program_options.html), etc. But I wondered if there is one that lets me encode these conditional relationships between arguments directly, w/o manually coding error handling
if ( argR.isSet() && ( ! argI.isSet() || ! argO.isSet() || ... ) ) ...
and manually setting up the --help.
The library tclap allows to XOR arguments, e.g. either -a or -b is allowed but not both. So, in that terminology an AND for arguments would be nice.
Does anybody know a versatile, light-weight, and cross-platform library that can do that?
You could two passes over the arguments; If -r is in the options you reset the parser and start over with the new mandatory options added.
You could also look into how the TCLAP XorHandler works, and create your own AndHandler.
You could change the argument syntax so that -r takes four values in a row.
I have part of the TCLAP snippet of code lying around that seems to fit the error handling portion that you're looking for, however it doesn't match exactly what you're looking for:
# include "tclap/CmdLine.h"
namespace TCLAP {
class RequiredDependentArgException : public ArgException {
public:
/**
* Constructor.
* \param text - The text of the exception.
* \param parentArg - The text identifying the parent argument source
* \param dependentArg - The text identifying the required dependent argument
* of the exception.
*/
RequiredDependentArgException(
const TCLAP::Arg& parentArg,
const TCLAP::Arg& requiredArg)
: ArgException(
std::string( "Required argument ") +
requiredArg.toString() +
std::string(" missing when the ") +
parentArg.toString() +
std::string(" flag is specified."),
requiredArg.toString())
{ }
};
} // namespace TCLAP
And then make use of the new exception after TCLAP::CmdLine::parse has been called:
if (someArg.isSet() && !conditionallyRequiredArg.isSet()) {
throw(TCLAP::RequiredDependentArgException(someArg, conditionallyRequiredArg));
}
I remember looking in to extending and adding an additional class that would handle this logic, but then I realized the only thing I was actually looking for was nice error reporting because the logic wasn't entirely straightforward and couldn't be easily condensed (at least, not in a way that was useful to the next poor guy who came along). A contrived scenario dissuaded me from pursuing it further, something to the effect of, "if A is true, B must be set but C can't be set if D is of value N." Expressing such things in native C++ is the way to go, especially when it comes time to do very strict argument checks at CLI arg parse time.
For truly pathological cases and requirements, create a state machine using something like Boost.MSM (Multi-State Machine). HTH.
do you want to parse a command line?you can use simpleopt,it can be used as followings:downLoad simpleopt from:
https://code.google.com/archive/p/simpleopt/downloads
test:
int _tmain(int argc, TCHAR * argv[])
argv can be:1.txt 2.txt *.cpp