Recently, I am doing a job about porting.
I encountered such a problem:
Some Windows API, such as _clearfp(), _statusfp() etc, then I can't find the corresponding functions in Linux.
So I am here to ask for help.
You would need a POSIX system, or a C99 compiler that supported Annex F of the C99 Standard. You can test if Annex F is supported by checking if the macro __STDC_IEC_559__ is defined. The relevant functions would be found in <fenv.h>.
int feclearexcept(int excepts); // clears exceptions (returns 0 on success)
int fetestexcept(int excepts); // returns exceptions that are set
The exceptions passed in as excepts, and returned by fetestexcept, is a bitmask that can be test against the following macros:
FE_DIVBYZERO
FE_INEXACT
FE_INVALID
FE_OVERFLOW
FE_UNDERFLOW
FE_ALL_EXCEPT
The last macro, FE_ALL_EXCEPT, is just the bitwise-or of all the macros above it.
Related
In NSIS, I was going through some API which calls some functions of Windows.
For example:
Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0
Kernel32::GetLocaleInfo(i,i,t,i)i(2048,0x2,.r0,${NSIS_MAX_STRLEN})i
As I am a newbie, can anyone please explain what is happening here ? What is t , i , .ro etc. ?
I know that kernel32 is a DLL and SetEnvironmentVariable & GetLocaleInfo are the functions defined in this DLL.
The documentation will tell you what t and i are.
The basic syntax for System::Call is module::function(parameters)return. Parameters and return are optional and they both follow the same basic format: type input output. Type is not optional if you need input and/or output.
Parameters and return can be repeated multiple times, this is only useful when the function prototype exists as a define but you sometimes see this syntax on the NSIS Wiki as well. Kernel32::SetEnvironmentVariable(t, t)i ("VAR1", "$R0").r0 is exactly the same as Kernel32::SetEnvironmentVariable(t "VAR1", t "$R0")i.r0. When using a define it would look like this:
!define SetEnvironmentVariable "Kernel32::SetEnvironmentVariable(t, t)i"
System::Call '${SetEnvironmentVariable}("VAR1", "$R0").r0'
It is helpful if you know a language like C/C++ or Delphi when using the System plug-in because you need to understand the basic Windows types and how functions are typically used.
If for example you wanted to call the GetWindowsDirectory function you would first look at the function on MSDN:
UINT WINAPI GetWindowsDirectory(_Out_ LPTSTR lpBuffer, _In_ UINT uSize);
Translating this to NSIS gives you a initial skeleton of Kernel32::GetWindowsDirectory(t, i)i (WINAPI is the default calling convention). t maps to the Windows TCHAR* type and i is a 32-bit integer, the same as ULONG, LONG, DWORD, INT, UINT, INT32 and UINT32 in the Windows SDK.
The only missing piece is the input and output. The MSDN declaration is decorated with SAL annotations so it is easy to see which parameters are input and which are output.
A working example might look something like this:
System::Call 'Kernel32::GetWindowsDirectory(t .r1, i ${NSIS_MAX_STRLEN})i .r0'
DetailPrint "Return=$0 Output1=$1"
. can be used as a "nothing" placeholder when there is no input. In this case we use it twice. The return value never has input when using System::Call and we also have one output-only parameter.
r1 and r0 are aliases for the $1 and $0 NSIS registers and these aliases must be used when you need the output of something. The plain NSIS register can be used as input but then the variable expansion happens inside NSIS and not in the plug-in and this can cause issues with quotes in strings and is not really recommended if the string might contain quotes or legal System plug-in syntax. I would therefore recommend that your first example is rewritten as Kernel32::SetEnvironmentVariable(t "VAR1", t R0)i.r0.
In C your second example would look something like
char mybuf[1024];
GetLocaleInfo(MAKELCID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT), LOCALE_SLANGUAGE, mybuf, sizeof(mybuf));
I have some mql5 code which I want to print debug messages if the DEBUG macro is set. I would like to use a different function (DebugPrint for that matter) for those debug messages. My first attempt was to create a regular function, but variable arguments don't seem to work. I then tried to use the precompiler to remove the DebugPrint-calls based on this answer, however the compiler's pre-processor doesn't seem to understand the variable argument list either. This is the code I tried:
#ifdef DEBUG
#define DebugPrint(...)
#else
#define DebugPrint(...) Print(__VA_ARGS__)
#endif
Any ideas on how to achieve what I'm trying to do?
My few cents on MQL4/5:
Preprocessor directives:
while the revised New-MQL4.56789 compiler has opened some new, more complex constructs for #define preprocessor directives syntax, I have almost always burnt my fingers when trying to use them in production code.
Variadic arguments:
MQL4/5 is a strong-typed, compiled language and as such does not provide means for variadic functions. With some recent syntax aids, coming from ( OOP ) Class-based function ( method ) call-interface overrides and maybe using some advanced abstractions from so called function-template-s, there are chances to create some sort of syntax-support for your #define-dependent behaviour.
Function Overloading,template-sandtypename-dependent actions:
Whereas these techniques have brought even more "New" compiler features into the MQL4/5 software domain, the additional levels of complexity do not justify the efforts, given the resulting principles are restricted from being usable in cases where their use is restricted from export, virtual or #import constructs.
So how to make this work?
Well, for the sake of the rapid & iterative development needs, one may resort to an "almost-variadic" PrintFormat( DEBUG_MASK, ..., ..., ... ); using a context-full (known) matching set of attributes against a static, context-specific #define-ed DEBUG_MASK. Nested construction of FormatString( MASK_A, par1, par2[, FormatString( MASK_B, par3, par4[, FormatString( ... )[, ... ] )[, ... ]) are left for one's own kind imagination.
I'm currently trying to learn Nim (it's going slowly - can't devote much time to it). On the other hand, in the interests of getting some working code, I'd like to prototype out sections of a Nim app I'm working on in ruby.
Since mruby allows embedding a ruby subset in a C app, and since nim allows compiling arbitrary C code into functions, it feels like this should be relatively straightforward. Has anybody done this?
I'm particularly looking for ways of using Nim's funky macro features to break out into inline ruby code. I'm going to try myself, but I figure someone is bound to have tried it and /or come up with more elegant solutions than I can in my current state of learning :)
https://github.com/micklat/NimBorg
This is a project with a somewhat similar goal. It targets python and lua at the moment, but using the same techniques to interface with Ruby shouldn't be too hard.
There are several features in Nim that help in interfacing with a foreign language in a fluent way:
1) Calling Ruby from Nim using Nim's dot operators
These are a bit like method_missing in Ruby.
You can define a type like RubyValue in Nim, which will have dot operators that will translate any expression like foo.bar or foo.bar(baz) to the appropriate Ruby method call. The arguments can be passed to a generic function like toRubyValue that can be overloaded for various Nim and C types to automatically convert them to the right Ruby type.
2) Calling Nim from Ruby
In most scripting languages, there is a way to register a foreign type, often described in a particular data structure that has to be populated once per exported type. You can use a bit of generic programming and Nim's .global. vars to automatically create and cache the required data structure for each type that was passed to Ruby through the dot operators. There will be a generic proc like getRubyTypeDesc(T: typedesc) that may rely on typeinfo, typetraits or some overloaded procs supplied by user, defining what has to be exported for the type.
Now, if you really want to rely on mruby (because you have experience with it for example), you can look into using the .emit. pragma to directly output pieces of mruby code. You can then ask the Nim compiler to generate only source code, which you will compile in a second step or you can just change the compiler executable, which Nim will call when compiling the project (this is explained in the same section linked above).
Here's what I've discovered so far.
Fetching the return value from an mruby execution is not as easy as I thought. That said, after much trial and error, this is the simplest way I've found to get some mruby code to execute:
const mrb_cc_flags = "-v -I/mruby_1.2.0_path/include/ -L/mruby_1.2.0_path/build/host/lib/"
const mrb_linker_flags = "-v"
const mrb_obj = "/mruby_1.2.0_path/build/host/lib/libmruby.a"
{. passC: mrb_cc_flags, passL: mrb_linker_flags, link: mrb_obj .}
{.emit: """
#include <mruby.h>
#include <mruby/string.h>
""".}
proc ruby_raw(str:cstring):cstring =
{.emit: """
mrb_state *mrb = mrb_open();
if (!mrb) { printf("ERROR: couldn't init mruby\n"); exit(0); }
mrb_load_string(mrb, `str`);
`result` = mrb_str_to_cstr(mrb, mrb_funcall(mrb, mrb_top_self(mrb), "test_func", 0));
mrb_close(mrb);
""".}
proc ruby*(str:string):string =
echo ruby_raw("def test_func\n" & str & "\nend")
"done"
let resp = ruby """
puts 'this was a puts from within ruby'
"this is the response"
"""
echo(resp)
I'm pretty sure that you should be able to omit some of the compiler flags at the start of the file in a well configured environment, e.g. by setting LD_LIBRARY_PATH correctly (not least because that would make the code more portable)
Some of the issues I've encountered so far:
I'm forced to use mrb_funcall because, for some reason, clang seems to think that the mrb_load_string function returns an int, despite all the c code I can find and the documentation and several people online saying otherwise:
error: initializing 'mrb_value' (aka 'struct mrb_value') with an expression of incompatible type 'int'
mrb_value mrb_out = mrb_load_string(mrb, str);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~
The mruby/string.h header is needed for mrb_str_to_cstr, otherwise you get a segfault. RSTRING_PTR seems to work fine also (which at least gives a sensible error without string.h), but if you write it as a one-liner as above, it will execute the function twice.
I'm going to keep going, write some slightly more idiomatic nim, but this has done what I needed for now.
My program, PKGDAYMONR has the control option:
ctl-opt Main( CheckDailyPackages )
The CheckDailyPackages procedure has the following PI:
dcl-pi *n ExtPgm( 'PGMNAME' );
As you can see the ExtPgm parameter is not the name of the program. In fact, it’s what came over in the template source and I forgot to change it. Despite the wrong name in ExtPgm, the program runs without a problem.
If I remove that parameter and leave the keyword as just ExtPgm, I get the following message:
RNF3573: A parameter is required for the EXTPGM keyword when the
procedure name is longer than 10.
If I drop ExtPgm from the Procedure Interface altogether, it also complains:
RNF3834: EXTPGM must be specified on the prototype for the MAIN()
procedure.
So why is it that I have to specify a parameter if it doesn't matter what value I enter?
O/S level: IBM i 7.2
Probably worth pursuing as a defect with the service provider; presumably for most, that would be IBM rather than a third-party, as they would have to contact IBM anyhow, given the perceived issue is clearly with their compiler. Beyond that, as my "Answer", I offer some thoughts:
IMO, and in apparent agreement with the OP, naming the ExtPgm seems pointless in the given scenario. I think the compiler is confused while trying to enforce some requirements in validations of the implicitly generated Prototype for the linear-main for which only a Procedure Interface is supplied; i.e. enforcing requirements that are appropriate for an explicit Prototype, but requirements that could be overlooked [thus are no longer requirements] in the given scenario.? I am suggesting that while the RNF3573 would seem appropriate for diagnosing EXTPGM specifications of an explicit Prototype, IMO that same effect is inappropriate [i.e. the validation should not be performed] for an implicit prototype that was generated by the compiler.
FWiW: Was the fixed-format equivalent of that free-form code tested, to see if the same or a different error was the effect? The following source code currently includes the EXTPGM specification with 'PGMNAME' as the argument [i.e. supplying any bogus value of 10-byte naming to supplicate the compiler, just as is being done in the scenario of the OP, solely to effect a successful compile], but could be compiled with the other variations with changes to the source, mimicking what was done with free-form variations, to test if the same\consistent validations and errors are the effect:
- just EXTPGM keyword coded (w/out argument); is RNF3573 the effect?
- the EXTPGM keyword could be omitted; is RNF3834 the effect?
- the D-spec removed entirely (if there are no parameters defined); ¿that was not one of the variations noted in the OP as being tried, so... the effect?
H MAIN(CheckDailyPackages)
*--------------------------------------------------
* Program name: CheckDailyPackages (PGMNAME)
*--------------------------------------------------
P CheckDailyPackages...
P B
D PI EXTPGM('PGMNAME')
/free
// Work is done here
/end-free
P CheckDailyPackages...
P E
I got a response from IBM and essentially Biswa was on to something, it simply wasn't clear (in my opinion) about the answer.
Essentially the EXTPGM is required on long Main procedure names in order to support recursive program calls.
This is the response I received from IBM explaining the reason for the scenario:
The incorrect EXTPGM would only matter if there was a call to the main
procedure (the program) within the module.
When the compiler processes the procedure interface, it doesn't know
whether there might be a call that appears later in the module.
EXTPGM keyword is used to define the external name of the program which you want to prototype. If you mention the EXTPGM then the program will be called dynamically.
Let us take an example in order to explain your query.
PGMA
D cmdExc PR ExtPgm('QSYS/QCMDEXC')
D 200A const
D 15P05 const
c callp cmdExc('CLRPFM LIB1/PF1':200)
C Eval *INLR = *ON
In the above example CmdExc used for the dynamic call to QSYS/QCMDEXC.
When we use the same program name as the EXTPGM parameter it acts as an entry point to the program when called from other programs or procedure.
But in any case when we mention any name as the sample parameter the EXTPGM will not give any error in compilation, but it gives the error during run time as it tries to resolve the name during run time.
As of Visual Studio 2005, the CRT has replaced most string functions with secure versions which add a size argument to indicate the limits of the destination buffer(s). This is fine, but it’s not clear how it should be used. Does it include the terminating zero? Take the following code for example:
…
TCHAR path[MAX_PATH] = TEXT("");
_tcscpy_s(path, MAX_PATH, filename);
…
Is it okay or does it induce an off-by-one error?
It'd be a failure of the API design to be MAX_PATH+/-1, as that would be confusing and lead to more buffer overflows.
Documentation states clearly for
dest[10] that _countof(dest) should be used, which would be 10
So a simple MAX_PATH will suffice.