Stringify preprocesor using macros to create a string with spaces - string

I'm attempting to create a string with spaces for my GUI title with some macros, I have this resource.h:
#define QUOTE(s) #s
#define xstr(s) QUOTE(s)
#define PACKAGE_NAME "SoundTest"
#define PACKAGE_VERSION_MAYOR 1
#define PACKAGE_VERSION_MINOR 8
#define PACKAGE_VERSION xstr(PACKAGE_VERSION_MAYOR.PACKAGE_VERSION_MINOR)
#define PACKAGE_STRING xstr(PACKAGE_NAME PACKAGE_VERSION)
The above produce this output in my window title: "SoundTest" "1.8" (with quotes);
I want this output: SoundTest 1.8 (without quotes). Any ideas?

PACKAGE_NAME already has quotes in it:
#define PACKAGE_NAME "SoundTest"
So if you stringify PACKAGE_NAME, you'll stringify the quotes as well, resulting in something like "\"SoundTest\"". (Remember that the C preprocessor just works with characters. It does not understand C datatypes.)
Fortunately, C lets you concatenate string literals just by writing them one after another, so that, for example, "SoundTest" " " "1.8" is a single string literal, just as though it had been written "SoundTest 1.8". You can use that to your advantage here:
#define PACKAGE_VERSION xstr(PACKAGE_VERSION_MAYOR.PACKAGE_VERSION_MINOR)
#define PACKAGE_STRING PACKAGE_NAME " " PACKAGE_VERSION

Does this work, its not the neatest solution though ?
#define PACKAGE_NAME SoundTest
#define PACKAGE_VERSION_MAYOR 1
#define PACKAGE_VERSION_MINOR 8
// not using this actually
#define PACKAGE_VERSION xstr(PACKAGE_VERSION_MAYOR.PACKAGE_VERSION_MINOR)
#define PACKAGE_STRING xstr(PACKAGE_NAME PACKAGE_VERSION_MAYOR.PACKAGE_VERSION_MINOR)

Related

How to force g++ to respect #define _POSIX_C_SOURCE 200809L

I need to use strerror_r to translate error numbers into human readable messages compiled with g++ on Linux Debian Bullseye. The man page notes:
int strerror_r(int errnum, char *buf, size_t buflen);
/* XSI-compliant */
char *strerror_r(int errnum, char *buf, size_t buflen);
/* GNU-specific */
strerror_r():
The XSI-compliant version is provided if:
(_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE
Otherwise, the GNU-specific version is provided.
We have two different types of the return value: int or char* depending on the version defined by _POSIX_C_SOURCE. I have this small test program:
~$ cat strerror_r.c
#include <string.h>
#include <stdio.h>
// #define _POSIX_C_SOURCE 200112L
// #undef _GNU_SOURCE
#define ERROR_BUFFER_LEN (size_t)256
int main(int argc, char **argv)
{
#if _POSIX_C_SOURCE < 200112L
char* ret;
#else
int ret;
#endif
char errorBuffer[ERROR_BUFFER_LEN];
int errno;
errno = 0;
ret = strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
fprintf(stderr, "Error message by pointer = '%s'\n", ret);
fprintf(stderr, "Content of errorBuffer = '%s'\n", errorBuffer);
return 0;
}
If I compile it with gcc everything is as expected:
$ gcc strerror_r.c && ./a.out; rm a.out
Error message by pointer = '(null)'
Content of errorBuffer = 'Success'
If I compile it with g++ I get this:
$ g++ strerror_r.c && ./a.out; rm a.out
strerror_r.c: In function ‘int main(int, char**)’:
strerror_r.c:24:21: error: invalid conversion from ‘char*’ to ‘int’ [-fpermissive]
24 | ret = strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char*
rm: cannot remove 'a.out': No such file or directory
If I try to force the needed version by uncommenting
#define _POSIX_C_SOURCE 200112L
#undef _GNU_SOURCE
I get:
$ g++ strerror_r.c && ./a.out; rm a.out
strerror_r.c:7: warning: "_POSIX_C_SOURCE" redefined
7 | #define _POSIX_C_SOURCE 200112L
|
In file included from /usr/include/x86_64-linux-gnu/bits/libc-header-start.h:33,
from /usr/include/string.h:26,
from strerror_r.c:3:
/usr/include/features.h:281: note: this is the location of the previous definition
281 | # define _POSIX_C_SOURCE 200809L
|
strerror_r.c: In function ‘int main(int, char**)’:
strerror_r.c:24:21: error: invalid conversion from ‘char*’ to ‘int’ [-fpermissive]
24 | ret = strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
| ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char*
rm: cannot remove 'a.out': No such file or directory
What I'm missing here? Why g++ does not compile the default thread save version of strerror_r? I need that version. How can I fix it?
Reference
Feature Test Macros
You need to specify the #define and #undef directives before you include any header files, so the first few lines should look like this:
#define _POSIX_C_SOURCE 200112L
#undef _GNU_SOURCE
#include <string.h>
#include <stdio.h>
That's because those header files or internal header files they include need those values defined to choose the proper variant. If you define them after including the headers, the headers don't see the right values and they don't include the version you want.
Often people specify these values on the command like with the -D and -U arguments so they are always specified before header files are included.

Inno Setup string concatenation in #define directive

Did the Inno Setup website fail to document the #define directives or did I miss that somewhere? Is it permissible to define using defined strings and concatenate them?
#define MyApp ABC
#define MyAppVersion 1.2.1
#define MyFolder ? ; what is the right syntax here to concatenate
; the two previously defined strings?
Here is the section of help concerning defines:
http://www.jrsoftware.org/ispphelp/index.php?topic=define
Regarding your example:
#define MyApp "ABC"
#define MyAppVersion "1.2.1"
#define MyFolder MyApp + MyAppVersion
#define MyFolder1 MyApp + "Some other string"

sed: insert a macro with backslashes and newlines before a line in a file

I have text in a file like:
#include<stdio.h>
#include<stdlib.h>
#define MIN 0
#define MAX 100
I want to insert a macro before the 1st #define like:
#include<stdio.h>
#include<stdlib.h>
#define MAXIMUM(a,b) \
(a>b?(return a):(return b))
#define MIN 0
#define MAX 100
I tried my luck with sed, but it wasn't so successful. I have to do this in a bash script, say add_macro.sh, which is executed as:
./add_macro file.c
and contains:
var1="#define"
var2="#define MAXIMUM(a,b) \ /\n(a>b?(return a):(return b))"
sed "H;${x;s/$var1 .*\n/$var2&/;p;}" $1 > $1.tmp
When I run the above script, it does something like:
#include<stdio.h>
#include<stdlib.h>
#define MIN 0
#define MAX 100
#include<stdio.h>
#include<stdlib.h>
#define MAXIMUM(a,b) //no '\' is printed
(a>b?(return a):(return b))
#define MIN 0
#define MAX 100
It repeats the data and does substitution only once.
Any help will be most appreciated.
var1="#define"
var2='#define MAXIMUM(a,b) \\ \
(a>b?(return a):(return b))'
sed "0,/^$var1/{/^$var1/s/$var1/$var2\n$var1/}" $1
or a bit shorter:
sed "0,/^$var1/s/^$var1/$var2\n$var1/" $1
var1="#define MIN"
var2="#define MAXIMUM(a,b) \\\\ \n(a>b?(return a):(return b))"
sed "s/${var1}.*$/$var2\n&/g;" $1 > $1.tmp
A simpler pattern:
var1="#define MIN 0"
var2="#define MAXIMUM(a,b) \\\\\n(a>b?(return a):(return b))"
cat test.c |sed "s%^\($var1\)$%$var2\n\1%g"
You get:
samveen#precise:/tmp$ bash replace.sh
#include<stdio.h>
#include<stdlib.h>
#define MAXIMUM(a,b) \
(a>b?(return a):(return b))
#define MIN 0
#define MAX 100
This also ensures that it'll replace only those lines that match just the exact contents of var1, ensured by the ^ and $ anchors in the pattern.
I got it:
var2='#define MAXIMUM(a,b) \\\n(a>b?(return a):(return b))'
var1='#define'
sed "H; 0,/^$var1 .*/s//$var2\n&/1;" $1 > $1.tmp
Thanks everyone for the input!

Testing a parameter passed through the /D command line switch fails in Inno Setup

I call ISCC /DENABLE_SIGNING=1 MyFile.iss, and in MyFile.iss I have:
#if ENABLE_SIGNING == 1
SignedUninstaller=yes
SignTool=mysigntool
#endif
ISPP fails with an error exactly at the line with #if ENABLE_SIGNING == 1:
[ISPP] Operator not applicable to this operand type.
But if I've defined ENABLE_SIGNING in the MyFile.iss instead, it goes fine. This code passes without errors:
#define ENABLE_SIGNING 1
#if ENABLE_SIGNING == 1
SignedUninstaller=yes
SignTool=mysigntool
#endif
Edit
Also, there is another problem, when I use /DENABLE_SIGNING=0, testing #if ENABLE_SIGNING succeeds, while if I use #define ENABLE_SIGNING 0, the check fails (meaning evaluates to false), as it should.
From some tests I've ran right now it seems the command line interpreted preprocessor takes the define default values as strings. So when you modify your condition this way, it will work properly:
; just for case when you wouldn't run ISCC from command line
#ifndef ENABLE_SIGNING
#define ENABLE_SIGNING "1"
#endif
[Setup]
AppName=My Program 1
AppVersion=1.5
DefaultDirName={pf}\My Program
#if ENABLE_SIGNING == "1"
SignedUninstaller=yes
SignTool=mysigntool
#endif

CPP expands macros in %-lines in rpcgen source file

Lines starting with sign '%' should be passed as is in output file,
but is such lines have some CPP macros, those macros are expanded as well:
Source (test.x):
#ifdef ONE
#warning "ONE is defined"
#else
#warning "NO ONE!!!!!1111"
#endif
%
% hello, ONE
%
Running rpcgen:
# rpcgen test.x -DONE
test.x:2:2: warning: #warning "ONE is defined" [-Wcpp]
test.x:2:2: warning: #warning "ONE is defined" [-Wcpp]
test.x:2:2: warning: #warning "ONE is defined" [-Wcpp]
test.x:2:2: warning: #warning "ONE is defined" [-Wcpp]
Result (test.h):
/*
* Please do not edit this file.
* It was generated using rpcgen.
*/
#ifndef _TEST_H_RPCGEN
#define _TEST_H_RPCGEN
#include <rpc/rpc.h>
#ifdef __cplusplus
extern "C" {
#endif
hello, 1
#ifdef __cplusplus
}
#endif
#endif /* !_TEST_H_RPCGEN */
So "ONE" is replaced with "1", but it is desirable leave it as is
(consider "#ifdef ONE" in resulting test.h)
It there any way to aviod it?
So, I have a workaroud with CPP wrapper:
somedir/cpp <- wrapped which undefines problematic macros. For example:
#!/bin/sh
exec /usr/bin/cpp -U_LP64
Run rpcgen as rpcgen -Y somedir

Resources