Visual Objects - Retrieving string DEFINE dynamically - #ifdef is returning false - clipper

This is regarding the Visual Objects programming language based upon Clipper.
I'm trying to load the values of a few DEFINE constants, I've tried using #ifdef to determine if they exist however it doesn't seem to work with strings, just numbers or logics, e.g.:
DEFINE TEST_LOGIC := True
DEFINE TEST_NUM := 1
DEFINE TEST_STRING := "HELLO"
#IFDEF TEST_LOGIC
// Runs
#ENDIF
#IFDEF TEST_NUM
// Runs
#ENDIF
#IFDEF TEST_STRING
// Does not run
#ENDIF
Is there some other way of determining whether they exist and returning their values? I've tried VarGet() and MemVarGet() but they can't see the constant and cause a runtime error, and #ifdef cannot accept a method call like !Empty(TEST_STRING) (will not compile), using a direct comparison like #ifdef TEST_STRING > " " also doesn't work (compiles and runs but the code block does not execute).

There doesn't seem to be a way to do this using DEFINE statements containing strings, however if it's changed to a GLOBAL declaration then the #ifdef statement will work as expected.

Related

How to change the values defined in header file in embedded c during runtime?

I am working on a project using MSP430FR6047 and there is certain header file I need to access and change parameters previously defined.
At the moment I have to flash the MCU with modified header file every time I change the parameter but I was exploring if there is another option to do theses changes without flashing the new code, preferably by UART or some other communication protocol.
So my question is how to change these parameters during runtime? Does any one know where should I start?
Thanks
A running program cannot change its source code, supposed that you mean something like #define PARAMETER 23. You need variables instead of constants.
One primitive solution is this:
Invent a global variable per parameter, declare all of them in an extra header file and define all of them in an extra source file for better maintenance.
In the new header file undefine all parameter macros and redefine them to use the variable instead of the literals.
In the using source files, include the original header file, after that include your new header file.
Initialize the variables initially, and change parameters as you wish during run time. (Initialization could be done in the new source file.)
This solution avoids heavy editing the using source files and leaves the original header file intact.
Example:
/* original.h */
#define PARAMETER 23
int f(void); /* returns PARAMETER */
/* new.h */
#if defined(PARAMETER)
#undef PARAMETER
#define PARAMETER parameter
#endif
extern int parameter;
/* new.c */
#include "new.h" /* ensures that declarations and definitions match */
int parameter = 23;
/* original.c */
#include "original.h"
#include "new.h"
int f(void) {
return PARAMETER;
}
/* main.c */
#include <stdio.h>
#include "original.h"
#include "new.h"
int main(void) {
PARAMETER = 42;
printf("%d\n", f());
}
If you like to change the original source code, feel free to get rid of all this preprocessor stuff, and directly use variables instead of constants. But then you should re-think your design and provide parameters as arguments to existing or new functions. Global variables should be avoided, reasons are left as an exercise to you.
There are 2 cases which change parameter in header file.
Case 1: Header define default value
For example, in header file you have:
#define DEFAULT_VALUE 10
then in .c file if it is using like:
if (a < DEFAULT_VALUE)
{ /* Do something */ }
If this is the case you could update as following:
Modified the original line:
if (a < var_DefaultValue)
{ /* Do something */ }
With var_DefaultValue is global variable:
int var_DefaultValue = DEFAULT_VALUE;
By default, this will work as original.
If you want to change value, you could create a thread to receive new value somewhere and then update to var_DefaultValue.
Case 2: Header file define some precompile tag. For example:
#define DEFAULT_FEATURE 1
and in .c file you refer to feature as following:
#if DEFAULT_FEATURE
/* Do Something */
#endif
For this case, it is impossible to change it by any mean.

Objective-C macro in preprocessor IF

I have a project with some macros that are defined using Objective-C statements, like this:
#define TEST [someObject someNumber] == 500
I need to define another value based on this result, like this:
#if TEST
#define THING = 1
#else
#define THING = 2
#endif
But, this doesn't work. And I can't use #ifdef TEST because the value is always defined. Even if it's false, it's still defined.
TEST is based on an ObjC statement, and it seems like the preprocessor has no way of evaluating it. So, is there no way to test for this?
In the comments you wrote:
Since TEST must be evaluated during runtime, there's no way to know the value of it during build time. Because the preprocessor can't know the value, it can't test it. Is this correct?
Yes.
The preprocessor runs (at least logically) before the rest of the compiler. It is essentially language and syntax agnostic, and does not even have access to constants defined in your code. The conditional constructs operate solely with preprocessor tokens.

Two different CMake difinitions

With CMake when some definitions are defined they are defined in this way:
add_definitions(-DMY_DEFINITION)
Sometimes I see people make the definitions in a different way:
add_definitions(-DMY_DEFINITION=1)
Then my question is what's the difference between them in the generated C++ project. Thanks.
This is not really related to CMake but more to the C/++ compiler.
In the code the difference is the same between :
#define MY_DEFINITION
and
#define MY_DEFINITION 1
Actually there's not need to define a value for a C/++ macro if the only thing you want is to know if the macro exists (has been defined), like a "flag". Best example is the header include guards :
#ifndef MYHEADER
#define MYHEADER
// ...
#endif
But sometimes people prefer setting a value (like =1) even if they don't need it, because it's more exhaustive, or clear.
More generally speaking when you affect a value to a macro it is because you expect the macro name to be expanded to the value. When not you just expect the value to exist. The way tests are done may be different :
With -DMY_DEFINITION:
#ifdef MY_DEFINITION
// Do something
#else
// Do somthing else
#endif
With -DMY_DEFINITION=1
#if MY_DEFINITION
// Do something
#else
// Do somthing else
#endif

Objective-c disable function with conditional macros

I have a custom logging function that i would like to disable for realease builds. But the problem is it only lets me to replace that function with another empty one. Here's what i would like to do:
#ifdef SMTH
#define logfunction(...)
#else
void logfunction(NSString *fmt, ...) { some logging code goes here }
#endif
To make this work, i could replace the function with a macro, including VA_ARGS and such, but ... the problem is that my xCode loses code completion inside the braces of logfunction(). Now if the logging facility is defined as a function - code completion works fine.
The only solution i have so far is this:
#ifdef SMTH
void logfunction(NSString *fmt, ...) { /* no code here */ }
#else
void logfunction(NSString *fmt, ...) { some logging code goes here }
#endif
This works fine, but there is a call to an empty function in release builds. Is there any way to work around this?
UPDATE - my bad - everything works
The first example actually works, i simply forgot to do the same conditional macro in the ".h" file ...
I think that your current solution is already good enough. The empty function wont cause much trouble (in terms of wasting much time when it is called). Probably the compiler will even remove the call to the empty function altogether.
However, if you still want to get rid of it, you can try what I am doing:
Wrap your log function into a macro, and define that macro conditionally.
Example:
#ifdef SMTH
#define logfunction(fmt, ...)
#else
#define logfunction(fmt, ...) __logfunction((fmt), ##__VA_ARGS__)
#endif
where __logfunction(NSString *fmt, ...) is your actual logging function. This will completely remove the call to the function, when your SMTH is set.
By the way, you may want to use the DEBUG flag, that is set per default in XCode for non-release builds (see the "Preprocessor Macros" setting in your target in XCode). You would need to switch the cases around inside the #ifdef, obviously, or make it a #ifndef DEBUG.

All values of an enum in an NSArray?

Hi all I have an enum type that holds my error codes.
The problem is that they are not sequential i.e.
enum{
ErrorCode1 = 1,
ErrorCode2 = 4,
ErrorCode3 = 74
}; typedef NSInteger MyErroCodes;
Also there are maybe 50 codes + so I really wouldn't want to have to duplicate the data or do it manually, which is what I've seen so far in my searches. Any help would be greatly appreciated.
The enum construct only exists at compile time. At run time, your MyErrorCodes instances are plain integers, and the ErrorCodeN values are just plain integer constants. There is no way to extract metadata from your enum in runtime (well, maybe there is in the debug info etc, but you don't want to go there...).
I suggest:
Create a small script (Python, Perl or whatnot) to generate functions that map the numeric code to string values. In XCode, you can even run code generators during the compilation phase if you really want.
Use metaprogramming or preprocessor macros to generate these functions during compilation. This requires some thought, but it can be done.
this is often accomplished using an include of a file which contains all the values within some body and sometimes using macros:
ErrorCode_enum.h
MON_ENUM_VALUE(ErrorCode1, 1)
MON_ENUM_VALUE(ErrorCode2, 4)
MON_ENUM_VALUE(ErrorCode3, 74)
where MON_ENUM_VALUE would be a variable macro expansion.
and your enum declaration might take this form:
enum {
#include "mon_enum_value_begin.h" // defines MON_ENUM_VALUE and such
#include "ErrorCode_enum.h"
#include "mon_enum_value_end.h" // undefines MON_ENUM_VALUE and everything else defined in mon_enum_value_begin.h
};
typedef NSInteger MyErroCodes;
then later you might write:
#include "mon_enum_NSNumber_begin.h" // defines MON_ENUM_VALUE and such
#include "ErrorCode_enum.h"
#include "mon_enum_NSNumber_end.h" // undefines MON_ENUM_VALUE and…
or
#include "mon_enum_NSError_begin.h" // defines MON_ENUM_VALUE and such
#include "ErrorCode_enum.h"
#include "mon_enum_NSError_end.h" // undefines MON_ENUM_VALUE and…
which may add or stringize those tags and values to other types.
Personally, I think the macros are gross, and just take alternate approaches (which, admittedly, may be more tedious to write).