Simple Ada program with wrong output - compilation

Complete beginner to Ada here.
I am trying to compile and run a simple Ada program, from here: http://www.dwheeler.com/lovelace/s1sf.htm
Here is the code:
-- Demonstrate a trivial procedure, with another nested inside.
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure Compute is
procedure Double(Item : in out Integer) is
begin -- procedure Double.
Item := Item * 2;
end Double;
X : Integer := 1; -- Local variable X of type Integer.
begin -- procedure Compute
loop
Put(X);
New_Line;
Double(X);
end loop;
end Compute;
I'm on Linux, using gnat so I do:
gnatmake -c compute.adb
gnatmake compute
Which gives me the executable. Running the executable gives a list of zeros, as it seems to initialize X to 0, even though it says to initialize it to 1, so I should get a list 1,2,4,...
Can anyone explain either where my code or my thinking is wrong? Oh and using gnat is there a way to compile and create the executable in a single command?

I can only guess that when you added "-gnato", gnatmake simply replied gnatmake: "compute" up to date. leaving you with the same executable.
brian#Gannet:~/Ada/Play$ gnatmake -gnato compute.adb
brian#Gannet:~/Ada/Play$ ./compute
1
2
...
536870912
1073741824
raised CONSTRAINT_ERROR : compute.adb:9 overflow check failed
Then without -gnato (I had to touch the source or I got the "up to date" message)
brian#Gannet:~/Ada/Play$ gnatmake compute.adb
brian#Gannet:~/Ada/Play$ ./compute
1
2
...
536870912
1073741824
-2147483648
0
0
0
0
which subsequently appears as a string of zeroes. Adding your extra "if" statement touched the file, forcing recompilation : the "if" itself is not strictly necessary (though testing and preventing constraint error is a Good Thing!)
The moral : without -gnato, or rather, without at least the flags -gnataoE -fstack_check, Gnat is not an Ada compiler.

As you double the integer value each time without any delay in the loop, it will overflow quickly. In GNAT, overflow checking is off by default, you can enable it with the -gnato switch. So when the integer value overflows, it finally gets 0 and that's what you're seeing (the output is too fast to see the initial numbers).
Compiling with -gnato should give you a constraint error on execution. You can also produce the executable with one line by executing
gnatmake -gnato compute.adb

Related

Reading a file in GHDL/VHDL

I am working on reading a text file in vhdl. There are many examples on this, but I am curious why this minimal showcase example doesn't work in GHDL. It works in ModelSim (by Mentor).
Is this because of missing features in GHDL? (I did not find anything in docs/ github issues)
Is this because of wrong standard that I am using without knowing?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use STD.textio.all;
entity test is
end test;
architecture behavioral of test is
file input : text;
begin
process
variable line_in : line;
begin
file_open(input, "input.txt");
while not endfile(input) loop
readline(input, line_in);
end loop;
wait for 100 ns;
end process;
end behavioral;
The output I get is:
./test:error: cannot open file "input.txt"
This means, there is no file/cannot be opened, but the file exists with correct access rights (proven in Modelsim). I tried this with full file name, too.
I'm using GHDL 0.37 on Linux with these flags:
--ieee=synopsys --std=08
If
file input : text;
is replaced with
file input : text open read_mode is "input.txt";
and
file_open(input, "input.txt");
is removed it works in GHDL.
However, I still don't know why the previous version did not work.
The example code is expected to fail. Note the lack of a procedure file_close call.
After the execution of the wait for 100 ns; wait statement the execution of the process statement will resume in a future simulation cycle. The statements in a process are executed in order and after the last statement (the wait statement) the first statement
file_open(input, "input.txt");
will be executed again.
Without an intervening file_close call a subsequent file_open call will fail.
IEEE Std 1076-2008
10.2 Wait statement
The timeout clause specifies the maximum amount of time the process will remain suspended at this wait statement. If no timeout clause appears, the timeout clause for (STD.STANDARD.TIME'HIGH – STD.STANDARD.NOW) is assumed. It is an error if the time expression in the timeout clause evaluates to a negative value.
11.3 Process statement
The execution of a process statement consists of the repetitive execution of its sequence of statements. After the last statement in the sequence of statements of a process statement is executed, execution will immediately continue with the first statement in the sequence of statements.
5.5.2 File operations:
In the second form of FILE_OPEN, the value returned through the Status parameter indicates the results of the procedure call:
— A value of OPEN_OK indicates that the call to FILE_OPEN was successful. If the call to FILE_OPEN specifies an external file that does not exist at the beginning of the call, and if the access mode of the file object passed to the call is write-only, then the external file is created.
— A value of STATUS_ERROR indicates that the file object already has an external file associated with it.
— A value of NAME_ERROR indicates that the external file does not exist (in the case of an attempt to read from the external file) or the external file cannot be created (in the case of an attempt to write or append to an external file that does not exist). This value is also returned if the external file cannot be associated with the file object for any reason.
— A value of MODE_ERROR indicates that the external file cannot be opened with the requested Open_Kind.
The first form of FILE_OPEN causes an error to occur if the second form of FILE_OPEN, when called under identical conditions, would return a Status value other than OPEN_OK.
The question use of the file_open procedure call is of the first form. The second form would fail returning a Status parameter value of STATUS_ERROR, already associating an external file with the file object input.
The fix for that would be to transform the wait statement to prevent the process from continuing to execute:
wait; -- wait for 100 ns;
end process;
or provide an explicit file_close call so a subsequent file_open call would succeed. (This would cause a lot of host activity for no useful purpose.)
The modified code could look like:
-- library IEEE;
-- use IEEE.STD_LOGIC_1164.all; -- NOT USED
use STD.textio.all;
entity test is
end test;
architecture behavioral of test is
file input : text;
begin
process
variable line_in : line;
begin
file_open(input, "input.txt");
while not endfile(input) loop
readline(input, line_in);
write (OUTPUT, line_in.all & LF);
end loop;
wait; -- wait for 100 ns; -- EXECUTE ONCE
end process;
end behavioral;
Yields:
%% ghdl -a --ieee=synopsys --std=08 test.vhdl
%% ghdl -e --ieee=synopsys --std=08 test
%% ghdl -r --std=08 test
some text
more text
yet some more text
getting boring
%%
Where a write to the file OUTPUT (the console) echos the contents of each line found in input.txt. Note that the end of line is removed by the readline procedure call and reintroduced to the string being written to OUTPUT.
So why does the different file declaration succeed?
architecture file_declaration of test is
-- file input : text;
file input: text open read_mode is "input.txt";
begin
process
variable line_in: line;
begin
-- file_open(input, "input.txt");
while not endfile(input) loop
readline(input, line_in);
write (OUTPUT, line_in.all & LF);
end loop;
wait for 100 ns;
end process;
end architecture file_declaration;
There's only one call to file_open, an implicit call during elaboration of the file declaration (6.4.2.5 File declarations). The file remains open yet there are no remaining lines to read, determined by the endfile call. Here the endfile call would occur every 100 ns, which would likely result in your CPU utilization to increase as test executes until TIME'HIGH is reached. Performing the endfile call would result in host file operations resulting in suspension and resumption of the ghdl model execution. An effective test of only making endfile procedure calls.
A wait statement (10.2) without a timeout clause (for 100 ns) will wait until TIME'HIGH effective ending the simulation without any intervening signal events or other process suspensions and resumptions or making TIME'HIGH/100 ns - 1 endfile procedure calls, each involving suspension and resumption of the shown process statement.
You could also specify a simulation stop time on ghdl's command line, matching the usage in Modelsim most likely:
%% ghdl -a --ieee=synopsys --std=08 test.vhdl
%% ghdl -e --ieee=synopsys --std=08 test
%% ghdl -r --std=08 test --stop-time=300ns
some text
more text
yet some more text
getting boring
./test:info: simulation stopped by --stop-time #300ns
%%
Host file operations can incur a significant execution time penalty. If you were to assign the read values to a signal or variable of a composite (array or record) type object they can be reused without waiting on host file operations.

Type of the actual argument differs from the type of the dummy argument

I have some demonstrative Fortran code (which is supposed to be successfully compiled) and try to compile in Intel Visual Fortran + VS2013. But I got an error during compilation
error #6633: The type of the actual argument differs from the type of the dummy argument
It seems the code in line 6 has some problem, but I cannot figure it out exactly
Aside: I can compile this code successfully within command line, so it's highly possible due to Visual studio setting. But I cannot figure out which option is responsible. Some solution suggest disabling the Check Routine Interface option, but it seems too dangerous.
SUBROUTINE FUNARR (A,N)
IMPLICIT NONE
INTEGER:: N
REAL,DIMENSION(N):: A
WRITE(*,*)"FUNARR VECTOR SUBSCRIPT....IN"
WRITE(*,'(10F12.6)')A(:N)
WRITE(*,*)"FUNARR VECTOR SUBSCRIPT....OUT"
A(:N)=A(:N)-100
END SUBROUTINE
PROGRAM WWW_FCODE_CN
IMPLICIT NONE
INTEGER,PARAMETER:: NMAX=100
REAL,PARAMETER:: PI=3.14159265
REAL,DIMENSION(NMAX):: ARR
INTEGER,DIMENSION(5):: VECSUBSCP=(/1,4,6,7,5/)
INTEGER:: NARR,I
NARR=10
ARR=1.
ARR(:NARR)=1.
WRITE(*,*)"ASSIGN TOTAL"
WRITE(*,'(10F12.6)')ARR(:NARR)
WRITE(*,*)
ARR(1)=-1.
WRITE(*,*)"ASSIGN ELEMENT"
WRITE(*,'(10F12.6)')ARR(:NARR)
WRITE(*,*)
ARR(2:4)=(/(SIN(PI*(I-1.)/(NARR-1)),I=2,4)/)
WRITE(*,*)"ASSIGN SLICE"
WRITE(*,'(10F12.6)')ARR(:NARR)
WRITE(*,*)
CALL FUNARR(ARR(2:4),3)
WRITE(*,*)"FUNARR SLICE"
WRITE(*,'(10F12.6)')ARR(:NARR)
WRITE(*,*)
ARR(VECSUBSCP(:3))=0.5
WRITE(*,*)"ASSIGN VECTOR SUBSCRIPT"
WRITE(*,'(10F12.6)')ARR(:NARR)
WRITE(*,*)
! ACTUAL ARGUMENT IS AN ARRAY SECTION WITH A VECTOR SUBSCRIPT
! DISCONTINUE,COPY,UNKNOWN POSITION,CANNOT BE INTENT(OUT)
CALL FUNARR(ARR(VECSUBSCP(3:5)),3)
WRITE(*,*)"FUNARR VECTOR SUBSCRIPT"
WRITE(*,'(10F12.6)')ARR(:NARR)
WRITE(*,*)
STOP
END PROGRAM WWW_FCODE_CN

invalid character name at (1)

I am trying to compile a fortran code. It will analyze an X file in an Y directory and then create a new file Z with the results. But there is something wrong occurring.
When I write the directory I see that it is too much for one line and then I try to continue it in the next one doing this:
namech='/home/matheus/Documents/UFABC/IC/Spectra/Elliptical/'
+ 'espec.fits'
But, when I try to compile using the command
gfortran Codigo.f -o TESTE -Lcfitsio -lcfitsio
I get this error message:
+ 'espec.fits'
1
Error: Invalid character in name at (1)
Can someone help me? Actually I do not know what this error is. The directory is 100% right. And when I move the archives to a simpler directory to be able to write everything in one line, it works! So is there something wrong with the "+"?
Thank you.
Edit1
Actually, when I add "&" in the end of the line, it gives me this error message:
namech='/home/matheus/Documents/UFABC/IC/Spectra/Elliptical/'&
1
Error: Unclassifiable statement at (1)
Codigo.f:60.7:
+ 'espec.fits'
1
Error: Invalid character in name at (1)
And with "//":
namech='/home/matheus/Documents/UFABC/IC/Spectra/Elliptical/'//
1
Error: Syntax error in expression at (1)
Codigo.f:60.7:
+ 'espec.fits'
1
Error: Invalid character in name at (1)
Edit2
Thank you so much for helping me. Well, I solved the problem switching to the ".f90" form.
Just one more question: do you know why it does not recognize the "c" for comments in the code? Thank you again! :)
This part of your compilation statement:
gfortran Codigo.f
will treat the source file, with its .f suffix, as fixed form source. This means that a continuation line is indicated by any character (other than a blank or a 0) in column 6.
However, the error message you get suggests that the + in the second line of your snippet is not in column 6 and that the compiler is treating it as the initial character in a new entity name for which it is not valid. The fact that the + is aligned, vertically, with n in the previous line strengthens my suspicion that this may the root of your problem.
Adding the ampersand, as suggested in a now-deleted answer, doesn't actually help in this case if you continue to tell the compiler that it is dealing with a fixed form source file. & is only used for continuation in free form source files. Adding the string-concatenation operator, //, doesn't help either since it is not followed by another string but a line ending. //& would help but is probably unnecessary.
I think you have 2 possible solutions, but choose only one:
Stick with fixed form and get the alignment right.
Change the file suffix to .f90 which will cause gfortran to treat the source file as free-form.
If you go for option 2 (which I would recommend) you can then either use & at the end of the continued line or you could simply merge the lines. In free-form the maximum line length is 132 characters.
Adding to High Performance Mark's answer:
If you continue with FORTRAN 77, most compilers have an option to increase the allowed line length, e.g., -ffixed-form -ffixed-line-length-none for gfortran. As already stated, Fortran >=90 has line length of 132, so you wouldn't need to split the line.
Finally, if you want to split the line in Fortran >=90, you need two ampersands. In most cases you need one, but to split a string you need two:
namech='/home/matheus/Documents/UFABC/IC/Spectra/Elliptical/&
&espec.fits'

Error: Invalid character in name at (1)

I am trying to compile a fortran file along with some .h files in FORTRAN. The .h files contain definition for common blocks of variable. When I compile them in Fortran, I get the following error:
integer knue,ke,knumu,kmu,knutau,ktau,ku,kd,kc,ks,kt,kb,kgamma,
1
Error: Invalid character in name at (1)
The code where this error occurs is,
Now my question is, does this "1" point where the error is?
The lines of code which this errors points is,
integer knue,ke,knumu,kmu,knutau,ktau,ku,kd,kc,ks,kt,kb,kgamma,
& kw,kz,kgluon,kh1,kh2,kh3,khc,ksnue,kse1,kse2,ksnumu,ksmu1,
& ksmu2,ksnutau,kstau1,kstau2,ksu1,ksu2,ksd1,ksd2,ksc1,ksc2,
& kss1,kss2,kst1,kst2,ksb1,ksb2,kn1,kn2,kn3,kn4,kcha1,kcha2,
& kgluin,kgold0,kgoldc
Also, is there something wrong with the way continuation are used. I am using gfortran to compile this file.
It looks like you are using Fortran 77 style line continuations and trying to compile with Fortran 90 style free format code. You either need to compile using the gfortran -ffixed-form option, or format the code using Fortran 90 style line continuations:
integer knue,ke,knumu,kmu,knutau,ktau,ku,kd,kc,ks,kt,kb,kgamma, &
kw,kz,kgluon,kh1,kh2,kh3,khc,ksnue,kse1,kse2,ksnumu,ksmu1, &
ksmu2,ksnutau,kstau1,kstau2,ksu1,ksu2,ksd1,ksd2,ksc1,ksc2, &
kss1,kss2,kst1,kst2,ksb1,ksb2,kn1,kn2,kn3,kn4,kcha1,kcha2, &
kgluin,kgold0,kgoldc
I had this problem when modifying scipy and trying to compile it. The following identation was necessary to make it work, with the star * at column 5. It works for both Fortran 77 and 90 styles.
double precision a,abseps,abserr,alist,area,area1,area12,area2,
* a1,a2,b,blist,b1,b2,correc,dabs,defabs,defab1,defab2,d1mach,
* dmax1,dres,elist,epmach,epsabs,epsrel,erlarg,erlast,errbnd,
* errmax,error1,error2,erro12,errsum,ertest,f,oflow,resabs,
* reseps,result,res3la,rlist,rlist2,small,uflow,areav
To your first question, yes the "1" normally denotes the point in the code where the error occurs. The code as such looks ok otherwise.
Actually the Fortran 77 continuation column is number six.
http://web.stanford.edu/class/me200c/tutorial_77/03_basics.html

Compiling Ruby Inline C code - resolving errors

I am trying to get this Ruby inline C code http://pastie.org/2825882 to work. The code works in vanilla C, but here I get errors and warnings. What causes this error?
./backtrack_inline.rb:67: error: lvalue required as unary '&' operand
Also, why do I get the following error?
./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'
Inspecting the resulting C code ( http://pastie.org/2826036) I fail to see anything wrong with the arguments. But I do also get the following warnings:
./backtrack_inline.rb:73: warning: passing argument 1 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 2 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 3 of 'backtrack' makes integer from pointer without a cast
Starting with this:
./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'
If you look at your generated code, the backtrack function is defined on line 29:
static VALUE backtrack(VALUE self, VALUE _ss, VALUE _s, VALUE _p, VALUE _mm, VALUE _ins, VALUE _del) { ... }
It has seven arguments, the original six, plus VALUE self as it has been converted into a method on the Scan class.
The call to this function, on line 67 looks like this:
end = backtrack(ss, s, p, mm, ins, del);
It has only six arguments. RubyInline doesn't convert this to a call to a method on the object, it simply copies it verbatim. This is also where the warnings about makes integer from pointer without a cast come from: the function definition has been converted to take VALUEs, but you're calling with the original types.
The error message says that the error is from line 73 in backtrack_inline.rb because of the directive on line 54 of the generated code:
# line 61 "./backtrack_inline.rb"
which basically tells the compiler to "reset" its line and file values for errors, and treat the next line (55) as being line 61 in the file ./backtrack_inline.rb. The actual line is 67, 12 ahead of 55, but the compiler reports it as being 73, 12 ahead of 61 (the value it was reset to) and from a differnt file. This technique doesn't really work in this case as it doesn't take into account the extra lines added by RubyInline. The actual line in the source is 69.
A simple fix for this is to change the definition of the backtrack function to be just a C function rather than add it as a method on the object. Change builder.c to builder.prefix (on line 38 of your Ruby file). This won't work if you want to have backtrack available as a method on the object in Ruby. If that's the case you might need create another function to be the method, which then wraps the "real" backtrack function.
Next, looking at
./backtrack_inline.rb:67: error: lvalue required as unary '&' operand
This actually refers to line 61 of the generated code, which looks like:
char* s = StringValuePtr(rb_iv_get(self, "#seq"));
StringValuePtr is a macro which is defined as:
#define StringValue(v) rb_string_value(&(v))
This is where the & in lvalue required as unary '&' operand comes from. You need to add a local variable to be the lvalue:
VALUE seq = rb_iv_get(self, "#seq");
char* s = StringValuePtr(seq);
In my case (Mac OS X Snow Leopard, Ruby 1.9.3-p0, RubyInline 3.11.0) these two changes made the script run without errors, but gave the warning:
backtrack_inline.rb:47: warning: implicit conversion shortens 64-bit value into a 32-bit value
This actually refers to line 46 of the ruby file:
return (s - ss) - 1;
s and ss are char *, i.e. 64 bit pointers (on this machine), and the return type of the function is int - 32 bits. Adding an explicit cast fixed this:
return (int)((s - ss) - 1);
It now runs cleanly:
ruby-inline $ ruby backtrack_inline.rb
14
ruby-inline $
(I hope 14 is the correct answer!)
Here's a version of the script with these changes.
OK, the question was also answered at Ruby Forum:
http://www.ruby-forum.com/topic/2959614
Ok... thought a bit more about this.
you are calling a variable end. While this isn't a reserved word in C - and ruby shouldn't be looking at it... perhaps ruby is getting confused?
I'd suggest you have a go at renaming it just in case. Worthwhile trying even just to rule it out.

Resources