Expanding a dynamic macro inside printf function - c

I want to compile a c program under different names. In the main file, I have the following macro:
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME "defaultname"
#endif
When compiling using gcc, I use -D switch to define this macro (is that the right term?):
$ gcc main.c -DEXECUTABLE_NAME="newname"
I do not know if the -D works fine or not because when I try to do something like the code below...it fails...I can not tell if the -D switch is screwing up or the syntax of using the macro inside the printf() function is not correct:
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
I get this error:
main.c:48:57: note: in expansion of macro ‘EXECUTABLE_NAME’
printf("no or invalid arguments. usage: %s [0,255]\n", EXECUTABLE_NAME);
Any suggestions?

It works, and you can see that because of the error. Which by the way is because you're defining your macro wrong on the command line, this is how you quote a string in a macro:
$ gcc main.c -DEXECUTABLE_NAME='"newname"'
And this said, it's not even needed. The executable path is always your first argument: *argv.

I tried this program with an integer, which is as follows
#ifndef EXECUTABLE_NAME
#define EXECUTABLE_NAME 2
#endif
int main()
{
printf("%d",EXECUTABLE_NAME);
}
and then typed gcc main.c -DEXECUTABLE_NAME=1 and it works as the value changes to 1. Is it a problem with the data type 'string' that you are using?

Related

How to send a variable from batch file to a C program?

How to use a variable from a batch file and send the value to a variable in a C file/program?
I absolutely do not know how to do this, and I don't know if it is even possible.
I am thinking about something like this:
Batch file:
#echo off
set name= %1
::somehow set a variable in myfile.c to "name"'s value
gcc myfile.c -o readf
.\readf
C file:
#include <stdio.h>
int main() {
char(or any other) name[] = /* the value of "name" in the batch file */
printf(name);
return 0;
}
As pointed out by #kopecs, it seem that you want to define a macro in the command line while compiling your code. This would be useful if you want to define some constant that will be included in the binary for future execution, but not if you simply want to get argument from the command line.
Modify your code the following way to use the preprocessor
#include <stdio.h>
#ifndef VARIABLE
// In case you want to define a default value for your VARIABLE
#define VARIABLE "default value"
#endif
int main() {
char(or any other) name[] = VARIABLE // VARIABLE is a preprocessing macro that will be defined by the compiler
printf(name);
return 0;
}
Then invoke the compiler with the following preprocessor option
#echo off
set name=%1
::somehow set a variable in myfile.c to "name"'s value
gcc myfile.c -o readf -D "VARIABLE=%name%" -Wall -Wextra -pedantic
.\readf
Documentation quote for the argument
-D name=definition
The contents of definition are tokenized and processed as if they appeared during translation phase three in a ‘#define’ directive. In particular, the definition is truncated by embedded newline characters.
If you are invoking the preprocessor from a shell or shell-like program you may need to use the shell’s quoting syntax to protect characters such as spaces that have a meaning in the shell syntax.
If you wish to define a function-like macro on the command line, write its argument list with surrounding parentheses before the equals sign (if any). Parentheses are meaningful to most shells, so you should quote the option. With sh and csh, -D'name(args…)=definition' works.
-D and -U options are processed in the order they are given on the command line. All -imacros file and -include file options are processed after all -D and -U options.
However, I would recommend using command line argument for your program, that would be more flexible and avoid to recompile it each time you want to change it (unless you want to redistribute the binary with the hardcoded string).
#include <stdio.h>
int main(int argc, char* argv[]) {
// add some sanity checking against argc before getting the value in argv
char(or any other) name[] = argv[1];
printf(name);
return 0;
}
and after compiling your code the with
gcc myfile.c -o readf -Wall -Wextra -pedantic
Just invoke with
.\readf name_value

Define multiple-word macro using -D flag with gcc

The purpose of this is to build a program with command line-injected macros, using a Makefile.
I would like to define macros using multiple terms, however I am given an error as subsequent parts of the string are treated as files by gcc.
An example of what I need is as follows:
#define ULL unsigned long long
#define T_ULL typedef unsigned long long ull_t
As a result, I am only able to create macros that contain 1 term per definition.
The latter attempt allows me to create parameterized macros, however those are also limited to 1 term per definition.
Attempted solution
#include <stdio.h>
#define _STRINGIZE(x) #x
#define STRINGIZE(x) _STRINGIZE(x)
int main(void)
{
# ifdef DEBUG
# ifdef STRING
printf("%s", "A STRING macro was defined.\n");
printf("string: %s\n", STRINGIZE(STRING));
# else
printf("%s\n", "A DEBUG macro was defined.");
# endif
# endif
}
Results
As described by the man page, under the -D option description.
$ gcc define.c -D='DEBUG' ; ./a.out
A DEBUG macro was defined.
As described by this answer, as an alternative approach.
$ gcc define.c -D'DEBUG' ; ./a.out
A DEBUG macro was defined.
$ gcc define.c -D'DEBUG' -D'STRING="abc"' ; ./a.out
A STRING macro was defined.
string: "abc"
$ gcc define.c -D'DEBUG' -D'STRING="abc efg"' ; ./a.out
clang: error: no such file or directory: 'efg"'
A STRING macro was defined.
string: "abc"
$ gcc define.c -D'DEBUG' -D'STRING="abc efg hij"' ; ./a.out
clang: error: no such file or directory: 'efg'
clang: error: no such file or directory: 'hij"'
A DEBUG macro was defined.
string: "abc"
You don't need the STRINGIZE macro. The correct command-line syntax is:
gcc -DDEBUG -DSTRING='"abc def"' program.c
In other words, you need to quote the whole value of the defined macro, including C string delimiters (").
Then you can just do:
printf("string: %s\n", STRING);

How to create a macro string

I'm trying to define a string macro before compiling my C code. I've tried something like:
#include <stdio.h>
int main(void) {
printf("%s", AMEM);
return 0;
}
and I've tried to compile with:
gcc -D AMEM="Deus Abencoa" file.c
But I keep getting this message:
file.c:5:15: note: in expansion of macro ‘AMEM’
printf("%s", AMEM);
^
<command-line>:0:4: note: each undeclared identifier is reported only once for each function it appears in
file.c:5:15: note: in expansion of macro ‘AMEM’
printf("%s", AMEM);
Any idea of how to put it to work?
Your shell interprets (“eats up”) the double-quotes. Since they need to be part of the cpp macro (as the C compiler requires them to form a string), you must pass them to the compiler driver, which means escaping them from the shell. Try this:
gcc -D'AMEM="Deos Abencoa"' file.c
Or this (commonly seen with GNU autoconf):
gcc -DAMEM=\"Deos\ Abencoa\" file.c
Do note that there is no space after -D either.
gcc -D AMEM='"Deus Abencoa"' file.c
The shell removes the single quotes, leaving the double quotes visible to the compiler. Before, the shell removed the double quotes.

gcc macro define option doesn't work for string

Sample code:
main()
{
printf("%d\n", MARCO);
// printf("%s\n", MARCO);
}
When I try to use gcc -D option, I found the following command works:
gcc -D MARCO=12345 test.c
but when I change 12345 to a string:
gcc -D MARCO=abcde test.c
an error occurs:
error: ‘abcde’ undeclared (first use in this function)
I have tried -DMARCO=abcde, -DMARCO="abcde", -D MARCO="abcde"; all failed with that error.
Does this -D option only support integers?
The trouble is that double quotes are recognized by the shell and removed, unless you prevent the shell from doing so by escaping the double quotes (with backslashes) or enclosing them in single quotes (which is what I'd use):
gcc -DMARCO='"abcde"' test.c
The single quotes are stripped by the shell but that means that the double quotes are seen by the C preprocessor. You need to use the %s format, of course.
By changing the macro, you can stringify a non-quoted name on the command line:
#include <stdio.h>
#define STRINGIFY(x) #x
#define MACRO(x) STRINGIFY(x)
int main(void)
{
printf("%s\n", MACRO(MARCO));
return(0);
}
Compile that with gcc -o testprog -DMARCO=abcde test.c and you will find it produces the correct answer.
you can also use like this...
-DMACRO="\"abcde\""
Ref:
How do I pass a quoted string with -D to gcc in cmd.exe?
The macro MARCO is literally replaced by the string you entered and only then is the code compiled. Since there are no quotes around the string (the double quotes in two of the examples are interpreted as delimiters by the shell), the abcde is not interpreted as a string, but as an identifier. Since it isn't defined, the code fails to compile.

missing symbols that should be there

I'm stumped. Here is the output of ld.
/usr/lib/libvisual-0.6/actor/actor_avs_superscope.so: undefined reference to `visual_mem_free'
/usr/lib/libvisual-0.6/actor/actor_avs_superscope.so: undefined reference to `visual_mem_malloc0'
Here are the macros:
#define visual_mem_new0(struct_type, n_structs) \
((struct_type *) visual_mem_malloc0 (((visual_size_t) sizeof (struct_type)) * ((visual_size_t) (n_structs))))
#define visual_mem_malloc(size) \
visual_mem_malloc_impl (size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define visual_mem_malloc0(size) \
visual_mem_malloc0_impl (size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define visual_mem_realloc(ptr, size) \
visual_mem_realloc_impl (ptr, size, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define visual_mem_free(ptr) \
visual_mem_free_impl (ptr, __FILE__, __LINE__, __PRETTY_FUNCTION__)
Now it doesn't add up. One line's saying that visual_mem_free is missing, which is a macro. The other's saying that visual_mem_malloc0 is missing, but the code's actually calling visual_mem_new0, which suggests it sees visual_mem_new0.
priv = visual_mem_new0 (SuperScopePrivate, 1);
visual_mem_free (priv);
Any clues?
Edit: Bumping.. Maybe some fresh eyes can help?
Edit: By the way, I get no warnings/errors during compiling, nor linking.
Edit: Here's a couple of snippets from the preprocessor's output.
int lv_superscope_cleanup (VisPluginData *plugin)
{
SuperScopePrivate *priv = visual_object_get_private ((((VisObject*) ((plugin)))));
visual_mem_free_impl (priv, "actor_avs_superscope.c", 195, __PRETTY_FUNCTION__);
return 0;
}
And:
priv = ((SuperScopePrivate *) visual_mem_malloc0_impl (((visual_size_t) sizeof (SuperScopePrivate)) * ((visual_size_t) (1)), "actor_avs_superscope.c", 152, __PRETTY_FUNCTION__));
It looks like the macros are being expanded. I'm confused. Is __PRETTY_FUNCTION__ supposed to be expanded?
Interestingly enough, here's the output from strings.
$ strings .libs/actor_avs_superscope.so |grep malloc
visual_mem_malloc0_impl
visual_mem_malloc0
malloc
Chris: I'm just running ld /usr/lib/libvisual-0.6/actor/actor_avs_superscope.so.
And here's the output from nm:
$ nm actor_avs_superscope.o |grep malloc
U visual_mem_malloc0_impl
$ nm actor_avs_superscope.o |grep free
U visual_mem_free_impl
U visual_palette_free_colors
Macros in C code don't result in symbols in compiled executables. Probably what is happening is that some code you are compiling didn't #include these macros, so the compiler inferred that they were functions, and compiled calls to them. You can use -Wall and -Werror to make calls to undefined functions fail to compile.
Macros are handled during the pre-processing phase which comes before linking. So if the link-editor is giving you warnings about macro names then the macros were not expanded.
To see the results of pre-processing, you can use the /E flag. If your macros have been expanded, you would see the line:
visual_mem_free (priv);
changed to something like:
visual_mem_free_impl(priv, "filename.c", 32, "main");
Update
From your nm/strings output, the file actor_avs_superscope.o is not where the problem is. What other object (.o) files and static archives (.a) are used to create actor_avs_superscope.so? You should run nm on all of them in order to find who has the unexpanded macro name in them.
Feels like it's not reading your #defines -- try printing a message inbetween them just to check.
Also check the order of compilation of your files; does the call to visual_mem_new0 come after the #defines?
Your first error is against the installed library, /usr/lib/libvisual-0.6/actor/actor_avs_superscope.so and it looks like you are looking at the local library in your project strings .libs/actor_avs_superscope.so. Try running strings against the one in /usr/lib and you'll probably see the issue.
I'd either Install your updated library version or put it's directory in the LD_LIBRARY_PATH when you run it, something like $ LD_LIBRARY_PATH=./lib ./your_executable.

Resources