How to enable _USE_UNIX98 (Gcc/C++ v2.96) - c++

I've a C++ application that works in actual compilers (I compile it with eclipse).
Now, I need compile it on a very old compiler version (gcc/c++ v2.96) on a Redhat 7.3 with Kdevelop.
When I compile the app it gives the following error: swprintf undeclared.
wchar.h header it's included, but I saw this file in the RH7.3 OS and only declare this function if __USE_UNIX98 __USE_ISOC99 are declared.
How can I enable __USE_UNIX98?

GNU libc defines the features that should be enabled in all of its headers using a special system header <features.h>. If you define the appropriate macros, <features.h> will define __USE_UNIX98 for you.
The typical way to get all functions, regardless of what standard (if any) covers them, is by adding -D_GNU_SOURCE on the command-line. Getting only the functions covered by a specific standard requires defining the macro as specified in that standard using the value specified in that standard, such as -D_POSIX_C_SOURCE=200112L. The precise values that are supported on your particular implementation are probably easiest found by inspecting /usr/include/features.h manually.

From inspection of <features.h> defining _XOPEN_SOURCE to 500 or greater will cause __USE_UNIX98 to be defined

Related

How to detect OS without directive ifdef?

I have to reset system date and time either on Linux, or on Windows.
How do I check OS without using ifdef, or if defined?
With CMake, you can conditionally add files to a target by using generator expressions. With that, you can isolate any platform-specific code in files, and use them in your build specification as follows.
add_executable(reset-time
$<$<PLATFORM_ID:Darwin>:resettime-macos.cpp>
$<$<PLATFORM_ID:Linux>:resettime-linux.cpp>
$<$<PLATFORM_ID:Windows>:resettime-windows.cpp>)
And as #eeroika pointed out in the comments, a good alternative is
add_executable(reset-time
resettime-$<LOWER_CASE:${CMAKE_SYSTEM_NAME}>.cpp)
as it requires not adjustment (of the CMakeLists.txt) when porting your project to a new system and you can catch a missing implementation file earlier, i.e., before linking.
You could set a global macro definition to the compiler based on which operating system you are compiling for. For example -D IS_WINDOWS=1. You could then use #if IS_WINDOWS instead of #ifdef. I don't know why this would be useful but it achieves what you asked.

Pycparser not working on preprocessed code

I need to use pycparser on preprocessed C code (the results produced by 'gcc -E'). However I am currently running into issue that I can't understand or solve.
I am using the provided samples year2.c and func_defs.py, which i modified to use a variety of preprocessors and fake libraries to no avail. Maybe some of you can look into this and see if you can reproduce/solve the issue. I will append all necessary code.
The errors were generated using year2.c (regular sample file) and year2.i ('gcc -E' output). There was no useable result for the latter while the former worked with both preprocessor/fakelib variants.
I have created a bitbucket repo with all relevant errors, the script used (albeit only its last variation) and the year2.c and year2.i files.
Error & Sample Repo
Thanks for your time.
The error you're getting is:
pycparser.plyparser.ParseError: /usr/lib/gcc/x86_64-linux-gnu/4.8/include/stdarg.h:40:27: before: __gnuc_va_list
The line indicated as causing the error (stdarg.h:40):
typedef __builtin_va_list __gnuc_va_list;
In gcc, __builtin_va_list is, as its name indicates, built in to the compiler. Consequently, no declaration of that type is necessary (or allowed).
It's pretty common for C compilers to use a symbol-table-based technique to parse typenames, since there are a number of ambiguities in the grammar if you cannot distinguish a typename from another identifier. Such a parser will assume that an undeclared identifier is not a typename, and if __builtin_va_list is not a typename, that typedef is a syntax error.
So I suppose that the pyparser grammar you're using doesn't know about gcc builtin types (and why should it?).
Your fakelib seems to be including the same header file. That's not surprising since it is hard to fake stdarg.h; although technically a library header, it is part of the small set of headers which must be provided by the compiler even in a freestanding (no standard library) implementation: <float.h>, <iso646.h>, <limits.h>, <stdalign.h>,
<stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and
<stdnoreturn.h> (C11 standard, clause 4, paragraph 6). These must be implemented by the compiler because there is no way an external library can know enough about the nature of the compiled code to properly define them.
Depending on what you require from the pyparsed output, you may be able to workaround this for pyparser by including a definition of __builtin_va_list, such as:
typedef struct __builtin_va_list { } __builtin_va_list;
__builtin_va_list is not the only builtin gcc datatype, although you may not run into the other ones. So you might have to iterate this solution a few times until you achieve whatever it is you are trying to achieve.
As #rici has explained the cause of the error. I'd focus more on how to solve it. I've taken my answer from pycparser author's blog -
http://eli.thegreenplace.net/2015/on-parsing-c-type-declarations-and-fake-headers
The idea is that pycparser needs to know what anyheader.h contains so it can properly parse the code. As actually parsing anyheader.h and all the other headers it transitively includes, could be very time consuming and perhaps not required for your task, fakeheaders can be used. A fake anyheader.h will only contain the parts of the original that are necessary for parsing - the #defines and the typedefs.
gcc -nostdinc -E -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c
The above command preprocess test.c which contains <stdio.h> using fake headers provided with pycparser package. -nostdinc flag is used to block some pre-set system header directories that gcc automatically includes. Now, parsing the preprocessed file, using e.g. below code
import pycparser
pycparser.parse_file('testPP.c')
should work in the most of the cases. If it doesn't make sure you provide all the dependencies for preprocessing.
In case, for some headers fakes are not provided, you can fake error causing typedef using #defining e.g. to resolve an error caused by __builtin_va_list, you can try faking it as follows:
gcc -nostdinc -E -D'__builtin_va_list(x)=' -I/home/rg/pycparser-master/utils/fake_libc_include test.c > testPP.c

gcc Make sure that no c++ isms are compiled?

If I use gcc as a driver, call all my source files .c and .h, can I be sure that I wont have any C++ source in my sources? Are there any gcc parameters to make sure that he throws errors in case any c++ is encountered in the source?
I am especially paranoid about include files, because I am not 100% sure whether I include C headers or C++ headers.
Some examples I ran into in the past:
trying to use the type bool
using wrong includes cstdio vs. stdio.h
trouble with the struct keyword
I just want to make 100% sure that my source is only C and has no C++ in it.
GCC will figure out itself whether it's a C or a C++ source code. How? It scans the file extension the file you passed has.
These are the extensions accepted.
In case you want to force a specific language, use the -x flag (documented in the link above). Furthermore, you may check whether the macro __cplusplus is defined.

Why is Xcode 4.2 applying C files build rule script for .cpp files?

I have an Xcode 4.2 project which includes a target that cross-compiles for windows. I use custom build rules for C source files and C++ source files in that target, invoking i386-pc-mingw32-g++ via a custom script. For some reason, Xcode runs the custom script I have specified as being for C source files, even when compiling files with a .cpp extension. Why might this be? How can I get Xcode 4.2 to run the "C++ source files" script for my .cpp files?
I also have .c files in this project, and am hoping to use -std=c++11 flag when compiling c++ files to enable some c++11 features. If I compile the .c files with this flag, I end up with weird scoping issues on constants included from math.h that I have yet to really try and understand - I am hoping I can just get Xcode to run the correct script for my .cpp files.
Any ideas?
Update: I've been able to get Xcode to run the correct scripts. To do this, I had to change the Process drop-down menu selections from "C source files" and "C++ source files" both to "Source files with names matching:" and then manually enter *.c and *.cpp in the provided text field. Now I have to figure out why I'm getting an M_PI was not declared in this scope error message where I wasn't before - maybe a different version of math.h is being used with the -std=c++11 flag which either doesn't include the M_PI constant or provides it under a different namespace?
Update: Continuing to work on this - it appears the M_PI value I was using from math.h is actually a macro which is only #define'd if __STRICT_ANSI__ has not been defined. Apparently switching to c++11 by using the -std=c++11 compiler flag has caused this __STRICT_ANSI__ macro to be defined, and thus the M_PI macro I was previously using isn't there. I suppose it's better to just define my own pi constants than to mess with the declaration of this __STRICT_ANSI__ macro, but I'll probably dig into that a bit just to clarify why it is being declared now that I'm using the c++11 flag.
Update: I found this post How can I make C++0x and __STRICT_ANSI__ get along?, which just suggests undefining the 'STRICT_ANSI' macro right after the '-std=c++11' flag (or rather, the equivalent '-std=c++0x' flag. While this seems sketchy, no one has posted encountering any problems because of it and it appears to work just fine for me as well in this case. Gcc documentation on this macro is located here: http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html, with the following relevant statement:
The macro STRICT_ANSI is predefined when the -ansi option is used. Some header files may notice this macro and refrain from declaring certain functions or defining certain macros that the ISO standard doesn't call for; this is to avoid interfering with any programs that might use these names for other things.
Still not sure why the '-std=c++11' flag causes this to be defined when it isn't by default (which would be '-std=c++98', apparently).
If you want C++11 support without ANSI mode, use -std=gnu++11 instead of std=c++11.

How to detect if errno_t is defined?

I'm compiling code using gcc that comes from Visual C++ 2008. The code is using errno_t, but in some versions of gcc headers including <errno.h> doesn't define the type. How do I detect if the type is defined? Is there a define that signals that the type was defined? In the case it isn't defined I'd like to provide the typedef to let the code compile correctly on all platforms.
Microsoft's errno_t is redundant. errno is defined by the ISO C standard to be a modifiable lvalue of type int. If your code needs to store errno values, then you should put them into an int.
Do a global search and replace s/errno_t/int/ and you're done.
Edit: Also, you shouldn't be providing a typedef int errno_t in your code, because all names that end with _t are reserved.
You can't check for a typedef the way you can for a macro, so this is a bit on the tricky side. If you're using autoconf, this patch shows the minimum changes that you need to have autoconf check for the presence of errno_t and define it if it's missing (the typedef would be placed in a file that includes your generated config.h and is included by all files that need errno_t). If you're not using autoconf you need to come up with some way to do the same thing within your build system, or a very clever set of tests against compiler version macros.
This is typically the case where GNU autoconf comes to the rescue. Basically autoconf will generate a configure script that can detect various system-dependent features such as whether this type exists and how it is defined. You then include the generated C header file within your application.
If you know which versions of GCC are giving you trouble, you can test for them. You can check for versions of GCC using something like:
#if __GNUC__ == 3
...
#else
...
#endif