Why is the default function parameter getting rejected in Free Pascal? - pascal

The following code:
program Default_Issue;
function SomeFunction(var myVar : integer;
defaulted : boolean = true) : integer;
begin
writeln('Inside SomeFunction');
SomeFunction := 0
end;
var
i : integer;
begin
SomeFunction(i,true);
end.
Gets a compiler error pointing to the = sign in the function declaration:
Default_Issue.pas(3,64) Fatal: Syntax error, ")" expected but "=" found
The program will compile if the function declaration line has the default parameter value removed:
function SomeFunction(var myVar : integer;
defaulted : boolean) : integer;
In the Free Pascal manual it shows default parameters as an option for value parameters and the syntax appears to be "var-name : type = value" so I don't understand why I am getting the compiler error.

Features are divided over languages modes. Default parameters is a delphi feature and some of those are only enabled in the objfpc and Delphi dialects.
The default (FPC) dialect is Turbo Pascal compatible, and TP didn't have default parameters.
Add -S2 or -Sd parameters. (FPC mode has overloading though, which can be used to mimic it)
Sometimes there is confusion because Lazarus defaults to objfpc mode by passing extra parameters.

Free Pascal has five compiler modes: (FPC, OBJFPC, TP, DELPHI, MACPAS).
The default compiler mode is FPC. Default function/procedure parameters are not supported in FPC mode. To use them you have to change the compiler mode to one that supports default function/procedure arguments. This can be done in the source code or on the command line. Default parameters are supported in the OBJFPC mode (the extended Free Pascal mode that gives you all the Free Pascal features) and also in the DELPHI mode (which aims for as much Delphi compatibility as possible).
To change the compiler mode in source code use the {$mode xxxx} compiler directive:
Program UseDefaultParameters;
{$mode OBJFPC}
The people who wrote the Lazarus IDE must think that this should be the default mode as they automatically add this source code compile mode whenever you ask it to create a new (Unit, Application, Program, Console Application, Library, InstantFPC program, FPCUnit Console Test Application, FCPUnit Test Application) file. The only time that the Lazarus IDE creates a file that doesn't have the OBJFPC compiler mode set is when it creates a new Simple Program.
To change the compiler mode on the command line use the -M compiler mode switch:
fpc -Mobjfpc my_program.pas

As I can see, your problem is in the function declaration, unexpected bracket after integer:
wrong:
function SomeFunction(var myVar : integer; defaulted : boolean = true) : integer )
right:
function SomeFunction(var myVar : integer; defaulted : boolean = true) : integer;

Related

Pascal Syntax error near unexpected token

I am trying to figure out the issue with this piece of Pascal code
function Factorial(n: integer): integer;
begin
if n = 0 then
Result := 1
else if n > 0 then
Result := Factorial(n - 1) * n;
end;
When I run the code I get the error
-bash: syntax error near unexpected token `n:'
Anyone can tell why that is? I am using the fpc (free pascal compiler) is this code meant for a different Pascal compiler?
That code compiles fine in fpc.
From the error message you quote, as #KenWhite says, it sounds like you are using the wrong tool to try to compile it - bash is an operating system shell for Linux and it is a bash error message. bash is not for comiling Pascal code.
I suggest you download and use Lazarus, which is the freeware IDE for fpc and runs on Linux and Windows. Once you have Lazarus installed on your system, create a new project (a "simple project" from Lazarus's list of new project types. Then copy/paste the code above the begin ...end of the project source, then save and compile it and you will see that Lazarus reports successfully compiling the project.
Btw, there is an omission from the code - it only covers cases where n is greater or equal to zero, so the function has an undefined result for n less that zero.

Two copies of constant appearing in the compiled Elf

We are basically using sparc architecture and our language is Ada we are using gnat compiler to compile our code.
We observed something funny.
Some of the constant in our code are having two or more copies.
file.adb:
With FileConsts; USE FileConsts
Procedure SomeProcedure is
A : LONG_FLOAT;
Begin
A := cSomeConstant;
End SomeProcedure;
FileConsts.ads
cSomeConstant : CONSTANT LONG_FLOAT := 100.0;
In the Map file we have basically
.rodata 0x40010000 (0x8)file.o
.rodata 0x40010008 pfileconsts__csomeconstant
In the Assembly it is accessing the area of file.o, i.e 0x40010000 instead if 0x40010008. In the binary file the value at 0x40010000 and 0x40010008 is actually same, so program is behaving as expected. But why would the compiler do that
If any other package(file2.adb) also accesses the cSomeConstant, it is making another copy in the section
.rodata 0x40010010 (0x8)file2.o
Again the value in binary file is same as cSomeConstant
Why compiler is behaving this way? How to suppress this behavior ?
It really is confusing while debugging.
You should remember that typed "constants" aren't static in Ada.
If you want a static constant, use a "named number":
Some_Constant : constant := 100.0;
(I don't know which code the compiler will generate in this case.)

How do I declare the precision of a number to be an adjustable parameter?

In 2013 there was a question on converting a big working code from double to quadruple precision: "Converting a working code from double-precision to quadruple-precision: How to read quadruple-precision numbers in FORTRAN from an input file", and the consensus was to declare variables using an adjustable parameter "WP" that specifies the "working precision", instead of having a separate version of the program with variables declared using D+01, and another version using Q+01. This way we can easily switch back and forth by defining WP=real128 or WP=real64 at the top, and the rest doesn't need to change.
But how do we do this?
I tried the suggestion in the answer to that question, by making a simple code TEST.F90:
PROGRAM TEST
use ISO_FORTRAN_ENV
WP= real128
IMPLICIT NONE
real (WP) :: X
X= 5.4857990945E-4_WP
END PROGRAM TEST
compiled with:
~/gcc-4.6/bin/gfortran -o tst.x TEST.F90
But it gives:
IMPLICIT NONE
1
Error: Unexpected IMPLICIT NONE statement at (1)
QLEVEL16.F90:5.12:
real (WP) :: MEL
1
Error: Parameter 'wp' at (1) has not been declared or is a variable, which does not reduce to a constant expression
QLEVEL16.F90:6.29:
MEL= 5.4857990945E-4_WP
1
Error: Missing kind-parameter at (1)
The kind specifier must be an integer parameter - and you do not declare it appropriately. Furthermore, implicit none must go before any declaration.
Here is a working version addressing both issues:
PROGRAM TEST
use ISO_FORTRAN_ENV
IMPLICIT NONE
integer, parameter :: WP= real128
real (WP) :: X
X= 5.4857990945E-4_WP
END PROGRAM TEST
Actually many code using this WP approach. Many with select_*_kind intrinsic function. But I think there is a 'easier' way. It's to use default precision without specifying any kind keyword andusing compiler's flag to choose what the default precision is.
Pro is this method is easier if you don't need a precise control of precision on each variable. Con is that will heavily depend on compiler flags, which varies for each compiler or even might not available.
For gfortran, there is more flags -freal4-real8 or -freal4-real16 to promote each explicitly specified lower precision variable to higher precision.

Get DLL caller info in Delphi

In a Delphi DLL need to establish the caller -- which may be a simple ".exe" or a DBMS runtime module -- which means it must obtain the command which is running in the process.
I know that CmdLine won't work, and probably ParamStr(0), and cannot use "main window" based techniques as caller will sometimes not have a window. I suspect that
GetModuleHandle is the starting point, but need assistance to get from there to command being executed.
I created a test dll:
library Project2;
uses
System.SysUtils, System.Classes, Vcl.Forms, Vcl.Dialogs, Winapi.Windows;
{$R *.res}
procedure DoStuff; stdcall;
begin
ShowMessage(
'ParamStr(0): '+ParamStr(0)+#13#10+
'GetCommandLine: : '+GetCommandLine);
end;
exports
DoStuff;
begin
end.
And then call it from a test application:
procedure TForm1.Button1Click(Sender: TObject);
var
module: HMODULE;
doStuff: procedure; stdcall;
begin
module := LoadLibrary('D:\Temp\Win32\Debug\Project2.dll');
if module = 0 then
RaiseLastOSError;
try
doStuff := GetProcAddress(module, 'DoStuff');
if #doStuff = nil then
raise Exception.Create('Could not find export "DoStuff"');
DoStuff;
finally
FreeLibrary(module);
end;
end;
And it sees the command line, using both:
ParamStr(0)
GetCommandLine
GetCommandLine obviously shows the entire command line, while ParamStr(0) is (by definition) just the process executable path.
In fact ParamStr(0) will work fine. It is, on Windows, implemented with a call to the API function GetModuleFileName, passing a value of 0 as the module handle. This retrieves the file name associated with the main executable module. This works just the same no matter that the call is made from a DLL or the main executable.
We don't really need to dig into the implementation if we would trust the Delphi documentation. Admittedly this can sometimes be a risky business! The documentation for ParamStr says:
ParamStr(0) returns the path and file name of the executing program (for example, C:\TEST\MYPROG.EXE).
If you need to know the arguments that were passed to the executable process, you can use ParamStr passing indices greater than zero. Or you could call GetCommandLine and parse the command line yourself.
Do beware that GetCommandLine will not always give the same executable file name as GetModuleFileName. The documentation says:
The name of the executable in the command line that the operating system provides to a process is not necessarily identical to that in the command line that the calling process gives to the CreateProcess function. The operating system may prepend a fully qualified path to an executable name that is provided without a fully qualified path.
All this feels a little dirty though. It might be cleaner to export an initialization function from the DLL and require callers to pass whatever information you need.

Problems with absoft fortran in mac

I used to work with Intel Visual Fortran and my code runs smoothly there. However I bought Absoft Fotran Compiler and I am getting many errors...
This is a sample program where I get errors
FUNCTION norm_inv(x)
USE nrtype
USE tauchen
IMPLICIT NONE
REAL(DP), INTENT(IN) :: x
REAL(DP) :: norm_inv,zbrent,x1,x2,tol
tol=1.0E-6
x1=-10.0
x2=10.0
norm_inv=zbrent(fni,x1,x2,tol)
CONTAINS
FUNCTION fni(x0)
USE nrtype
IMPLICIT NONE
REAL(DP), INTENT(IN) :: x0
REAL(DP) :: fni,norm_cdf
fni=norm_cdf(x0)-x
END FUNCTION fni
END FUNCTION norm_inv
And the Absoft compiler tells me
Message Number: 379
A procedure name is used as an actual argument to a function or
subroutine call, but the procedure name has not been given the
EXTERNAL attribute, is not a module procedure, or is not specified in
an interface block. NOTE: Giving the EXTERNAL attribute to the name
of the SUBROUTINE being compiled is an extension to the standard.
When I declare it external it tells me
Message Number: 552 The compiler detected a conflict in declarations
for this object. Because the object has the given attribute, it must
not be declared to be the new item.
fni is an internal procedure of the function norm_inv (where the call to zbrent is made). Passing an internal procedure as an actual argument is a feature new to Fortran 2008. Crucially, this is a feature implemented in the Intel compiler, but not the Absoft.
To make the code more "portable" working around things to make fni not internal would work. Merely adding the external attribute to fni would not be sufficient, and would indeed be incorrect.

Resources