Why could DDK successfully compile an invalid source file? - c

First, you can successfully compile the following main.c through DDK build utility.
#include <ntddk.h>
NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING)
{
try
{
leave;
}
except (1)
{
}
return 0;
}
And however, please note that:
Both of "leave" and "except" are not valid C-language kerwords.
I know both of __leave and __except (i.e. with double leading underscores) are microsoft-specific keywords to extend the C language, but "leave" and "except" not.
I also confirmed that "leave" and "except" are not defined by macro. MSDN explains none about this.
Who can give me an explanation? Thanks in advance.

As Rohan noted, they are defined by macro in warning.h. The definitions are there for backward compatibility with old code which used the non-underscore versions.

Related

Error C4576 in VS2015 enterprise

I have the error C4576 in Visual studio 2015 when I tried to compile the file: transcoding.c.
The source code of this file is here: transcoding.c
error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax
The error arise at line 127 in this instruction:
enc_ctx->time_base = (AVRational) { 1, enc_ctx->sample_rate };
I used the source of ffmpeg in my project
https://www.ffmpeg.org/download.html
I searched around for a solution but I'm not able to correct the error
If someone have found something similar, please provide an idea
Despite what some other answers incorrectly claim, VS2015 compiler provides comprehensive support for C99 features, including the compound literal feature you are trying to use in that problematic line.
One possible explanation for the error message is that it the source file, despite being named as .c file, is being compiled as C++ file. The project settings might explicitly request C++ compiler for this file. In C++ this code is invalid.
Check your compilation settings to see if it by any chance includes a /TP ("compile as C++") switch.
Old question, but...
The solution is pretty simple:
AVRational tb;
tb.num = 1;
tb.den = enc_ctx->sample_rate;
enc_ctx->time_base = tb;
or
enc_ctx->time_base.num = 1;
enc_ctx->time_base.den = enc_ctx->sample_rate;
Remove the parenthesis around the type in the macro definition.
That should work.
enc_ctx->time_base = AVRational { 1, enc_ctx->sample_rate };
Looks like a question where the C and C++ tags make sense. You're trying to compile C99 code with a C++ compiler. That doesn't work.

Call method from source file in another directory

I have a newbie question about the C programming language. I have looked around to find the answer in similar questions but I failed to figure it out.
Assume a simple project consisting of two dirs: src and test. The source and header files are defined by src/main.c, test/foo.h and test/foo.c.
src/main.c:
#include "../test/foo.h"
int main (void) {
int a = VAR; /* works, recognizes declared macro */
some_function(a); /* doesn't work, "undefined reference" */
}
test/foo.h:
#ifndef FOO_H
#define FOO_H
void some_function(int a);
#define VAR 2;
#endif
test/foo.c (redundant but to be complete):
#include "foo.h"
#include <stdlib.h>
void some_function(int a) {
printf("%d", ++a);
}
I created the project in Eclipse and I also compile with it, I figured it wasn't a linking error since the macro gets recognized but the method is not callable.
The reason why I'm using different directories is because I have a lot of files and would like my test code to be separate from my main source code. Note that src and test have the same parent directory.
Any ideas what's going on here? Am I missing something very obvious?
Any help would be much appreciated, thanks in advance!
edit: I'm working on a (Debian) Linux machine and Eclipse uses the gcc compiler.
edit2: Thanks to H2CO3's answer I learned it is indeed a linking error. Since compiling and linking manually every time is quite an overhead, I was wondering if anyone knows how to teach Eclipse to link executables from different directories?
--------------------- SOLUTION ---------------------
edit3: Lol the solution was very easy after all, all I had to do was create a "new source folder" rather than a "new folder". I feel stupid but thanks to you all for replying, H2CO3 in particular!
I figured it wasn't a linking error since the macro gets recognized but the method is not callable.
Non sequitur. Macros are expanded in the preprocessing phase. (And as such, they have nothing to do with linkage at all.) You do have a linker error.
What you have to do is compile both files then link them together, so something like this should work:
gcc -Wall -o dir_one/foo.o dir_one/foo.c
gcc -Wall -o dir_two/bar.o dir_two/bar.c
gcc -o my_program dir_one/foo.o dir_two/bar.o
Also, read this SO question/answer and/or this article to understand how the steps of the compilation process work together. (These are almost the same for C and C++, it's only the name mangling that usually differs.)

Can I export the used code from a c program with many compiler flags?

I would like to condense our linux driver code in to only the code that runs on the current kernel. It has parts that are ignored by if statements all the way back to kernele 2.4.x
Have you ever heard of a way to compile the code to an output which will be the working code with out all the stuff ignored by the c compiler if else statements?
I am wondering if we can run make something or gcc something that will simply result in all the code that is used for that build.
So like if I had this .c file below, then after running the make command I should have just the code I need for the newest kernel.
example.c
static somefunction .... {
avar = 0;
#if (linux_ver >= 2.6.31)
some newer code
#elseif (linux_ver >= 2.4.24)
some older code
#else
original code
#endif
}
after extracting / condensing, example.c would simply read as below
static somefunction .... {
avar = 0;
some newer code
}
The tool you are after is sunifdef or (more recent) coan.
See also: Is there a C pre-processor which eliminates #ifdef blocks based on values defined or undefined?
That's what the preprocessor directives do already. Try running the code through gcc -E (but prepare for a lot of output, as all #includes will be inlined).

Minix 3 stdio.h doesn't recognize FILE *f

I'm developing something on Minix 3 and, when it comes to deal with io files, I got a problem.
In the code:
#include <stdio.h> /* If I don't call any stdio funcs compiler doesnt's complain*/
int main() {
FILE * fp; /* I get the following: " * not expected " */
return 0;
}
Already tried everything that comes to my mind, can't figure it out..
/EDIT/
From what I can tell, when I include something, if I call functions not related to structs, it's OK. Is it the structs ?
I will assume you have checked whether the Minix file is present, that it really defines the type FILE and that your include path provides the correct -Ioption to the compiler to find that file.
Depending on your environment it could happen that an environment variable INCLUDE exists and is recognized by your compiler to provide additional include paths, recognized even before the include options from the command line. In such a case it might happen to include a stdio.hfrom a different compiler. Visual Studio is known to provide such an environment variable by default, and that has bitten me once before.
EDIT: Running the preprocessor in isolation may help to find out what is really happening in any case. Verify that FILEis defined in the preprocessed version of your file.

problems with memset in Metal C

I’m trying to initialize the Metal C environment with the following code, but get the following errors on the memset line.
ERROR CCN3275 IMIJWS0.METAL.SAMPLIB(MEM):6 Unexpected text ')' encountered.
ERROR CCN3045 IMIJWS0.METAL.SAMPLIB(MEM):6 Undeclared identifier ___MEMSET.
ERROR CCN3277 IMIJWS0.METAL.SAMPLIB(MEM):6 Syntax error: possible missing ')' or ','?
CCN0793(I) Compilation failed for file //'IMIJWS0.METAL.SAMPLIB(MEM)'. Object file not created.
Below is my code
#include &lt string.h&gt
#include &lt stdlib.h&gt
#include &lt metal.h&gt
void mymtlfcn(void) {
struct __csysenv_s mysysenv;
memset ( &mysysenv, 0, sizeof ( mysysenv ) );
mysysenv.__cseversion = __CSE_VERSION_1;
mysysenv.__csesubpool = 129;
mysysenv.__cseheap31initsize = 131072;
mysysenv.__cseheap31incrsize = 8192;
mysysenv.__cseheap64initsize = 20;
mysysenv.__cseheap64incrsize = 1;
The issue was with the search order. Although I did search(/usr/metal/include) from with in my JCL I didn't proceed it with a nosearch option, so string.h was getting picked up from the standard system librarys instead of the version included with Metal C. I've pasted my optfile dataset I passed to the CPARM below for refference.
//OPTIONS DD *
SO
LIST
LONG
NOXREF
CSECT
METAL
LP64
NOSEARCH
search(/usr/include/metal/)
So, I have no idea. But some suggestions:
You might try copying/pasting this code here from this example just to make sure it works 'as expected'
Maybe try defining some of the macros here? (when I did C programming on zOS, I had to do include some weird macros in order to get stuff to work. I have no reasonable technical explanation for this.)
You could try searching for memset() using "=3.14" (from ispf.) See if any other modules use that function, and then check the headers that they include (or macros that they define - either in the C files or H files) to make it work.
Another thought: before the memset(), try doing putting a printf() in. If you get a syntax error on the same line (only for printf, rather than memset) then you can see if the problem is before line 6 - like a misplaced parenthesis.
Finally, if i recall correctly, I had to compile my individual modules, and then link them manually (unless I wrote a JCL to do this for me.) So you might have to link once to link with your other modules, and then link again against the C library. Not to be pedantic, but: you're fairly certain that you're doing all of the link passes?
I realize that's a lot of hoops to try and you've probably already read the manuals, but maybe there is something useful to try?
Also, and you probably already know this, but this site (for looking up error codes) is infinitely useful. (along with the above links for full-text-searching the manual)
Edit: this page also talks about "built-in functions" - you could try (as stated at the bottom of the page) "#undef memcpy" to use the non-built-in version?
Can you show us your compiler arguments? You need to make sure that you're not pulling in the standard C header files in addition to the metal C ones. Here's an example:
xlc -c -Wc,metal,longname,nosearch,'list(./)' -I. -I /usr/include/metal -I "//'SYS1.SIEAHDRV'" -S -qlanglvl=extended foo.c
as -mrent -mgoff -a=foo.list -o foo.o foo.s
ld -bac=1 -brent -S "//'SYS1.CSSLIB'" -o foo foo.o
Are you missing the closing brace '}' for the function? How about any missing semi-colon line terminators? When missing braces/semi-colons the z/OS C compiler throws some strange/misleading messages sometimes. I don't have it to try out, but I'm assuming Metal does as well.

Resources