How can I be able to write C code with different command names instead of the existing, and also to get different compiling warning, errors etc?
For example, replace the 'while' loop declaration with 'foobar', so that:
foobar (i<10) i++;
will act as:
while (i<10) i++;
and to replace a compilation error message from:
prog.c:4:2: error: 'i' undeclared
to:
prog.c:4:2: banana kiwi: 'i' orange apple tomato
A use case for this is making C based on a human-language other than english.
For the input language, you can use macros to define alternate names for things.
#define foobar int
Or better to use typedef for types.
typedef int foobar;
Neither of these removes int from the namespace.
If the compiler is made using a grammar file and a compiler-compiler, then you may be able to edit the keywords in the grammar to change the names without introducing new names. This will be the .yacc or .bison or .antlr or sthg file.
For the error messages, those are going to be baked-in to the compiler or in a strings or config file. You'll have to edit those files, or better copy into new locale-variant and modify.
Or run the compiler with a filter that replaces error with banana kiwi. sed, awk, m4 -- many common tools for substitutions.
To give an alias to a type you can use typedef:
typedef int foobar;
foobar i; // is a int
About the error message, it's more complicated and is inside the compiler code...
Related
I'm using Doxygen 1.8.5 and having the same exact problem as in the following question, only the language is C and the enums are in the C files:
Doxygen C# XML comments: multiply enum's with same name and different scope got merged?
According to https://bugzilla.gnome.org/show_bug.cgi?id=522193 it was fixed in 1.6.0, but I'm guessing Doxygen isn't treating different C files as having different namespaces.
The enums in question pertain only to each specific file, but are called the same name because they are used for the same purpose in that file (for flags used to track status information about that module, for example). The C compiler has no problem with this, but Doxygen combines them.
Example:
file1.c
enum status_flags {
sfACTIVE,
sfSHUTDOWN,
sfWARNING,
};
file2.c
enum status_flags {
sfSTANDBY,
sfSCREEN_OWNED,
};
The doxygen file will generate a single blob of both enums combined, including the comments for each member, and reference them in the documentation for both files.
enum status_flags
Enumerator
sfACTIVE
sfSHUTDOWN
sfWARNING
sfSTANDBY
sfSCREEN_OWNED
Definition at line 42 of file file1.c.
and
enum status_flags
Enumerator
sfACTIVE
sfSHUTDOWN
sfWARNING
sfSTANDBY
sfSCREEN_OWNED
Definition at line 65 of file file2.c.
I've tried making each file a member of its own #addtogroup, and I've made sure each file has an #file at the top, but it's still mixing all of these enums together which are supposed to be private to that particular C file. It would be a bit of a pain if I were forced to rename each of these enums, as there are dozens of applications in the code which all follow a similar format and use private enums of the same name with different flags. The compiler is perfectly happy to work with them.
Any ideas?
Anonymous typedef enum also have this same issue,
typedef enum {
sfACTIVE,
sfSHUTDOWN,
sfWARNING
} status_flags;
results in the combining issue, but Doxygen appears
to give priority to the enumeration, so combining
does not happen when you do this:
typedef enum status_flags_f1 {
sfACTIVE,
sfSHUTDOWN,
sfWARNING
} status_flags;
typedef enum status_flags_f2 {
sfSTANDBY,
sfSCREEN_OWNED
} status_flags;
This only works if TYPEDEF_HIDES_STRUCT is set to NO in the Doxyfile configuration file, which is the default.
./theheader.h:349: Error: Syntax error in input(3).
Offending line:
string read_gdbm(GDBM_FILE dbf, string key_str, bool show_err = gbls.verbose);
Any ideas?
Typically, a syntax error in SWIG means that it can't understand the line in question (which can be annoying, because the line numbers don't follow macros such as %defines). So I suggest you check that string (should it be std::string? has it been defined?), GDBM_FILE (has it been defined? should it be in a namespace?) and maybe gbls.verbose (has it been defined?) make sense to SWIG. It may help to run swig with the -E option (be sure to redirect the stdout), find the corresponding line and search backward for each type involved. You may need to add some #includes.
Also check the previous line, to ensure you're not missing a semicolon, or something like that.
As a side note, I've run into the same issue for different reasons: I was trying to use a vector < vector < double >>. Now the ">>" character sequence mustn't be used with templates according to the C++99 standard, hence the swig error message popped up. The solution was to simply add an extra space to separate them.
I hit a similar error. I'll clarify my process, hope it can be helpful.
lib.i:
...
%begin %{
#include "header1.h"
%}
...
%include "header1.h"
header1.h:
19 typedef struct T {
...
23 } PACKED TlvHdr;
The error message just as below
./header1.h:23: Error: Syntax error in input(3).
I check the SWIG doc(http://www.swig.org/Doc1.3/SWIG.html 5.7.1) and found that the syntax error is so common, it's probably caused by a SWIG bug.
The doc recommended when encountering a syntax error to use #ifndef SWIG to omit statements that will make SWIG parser issue an error. So I changed the header1.h file, then the error disappeared.
header1.h:
#ifndef SWIG
19 typedef struct T {
...
23 } PACKED TlvHdr;
#endif
If you can't modify theheader.h file, you can make a new header file that just contains the declarations you need and replace the file from theheader.h to your new header file at %include directive
I had a similar issue and -E helped me understand that a macro definition was hidden inside an #ifndef SWIG block. I suspect that here it does not see the definition of GDBM_FILE, likely because it does not recurse.
In ruby there's very common idiom to check if current file is "main" file:
if __FILE__ == $0
# do something here (usually run unit tests)
end
I'd like to do something similar in C after reading gcc documentation I've figured that it should work like this:
#if __FILE__ == __BASE_FILE__
// Do stuff
#endif
the only problem is after I try this:
$ gcc src/bitmap_index.c -std=c99 -lm && ./a.out
src/bitmap_index.c:173:1: error: token ""src/bitmap_index.c"" is not valid in preprocessor expressions
Am I using #if wrong?
As summary for future guests:
You cannot compare string using #if
BASE_FILE is the name of file that is being compiled (that Is actually what I wanted).
Best way to do this is to set flag during compilation with -D
in gcc you can use:
#if __INCLUDE_LEVEL__ == 0
or:
if(!__INCLUDE_LEVEL__)
to check if your inside the __BASE_FILE__
Yes, you are misusing #if. It only works on integer constant expressions. But even if you were using if, comparing pointers for equality is never a valid way to compare strings in C.
It seems you can't.
Alternatively, it works perfectly fine on a regular if condition, and gcc can optimize this nicely.
if (!strcmp(__BASE_FILE__, __FILE__)) {
// works.
}
but you can't define new main functions or use other preprocessor tricks. but you could short-circuit main by using static methods, but that's harsh and dirty.
But maybe you shouldn't do it. in Ruby/python, this works because usage of files is done at runtime. in C, all files are to be compiled to be used.
Keep in mind that most build system will build one file at a time, building them as object files, and rebuilding them only when necessary. So
__BASE_FILE__ and __FILE__
will be equals most of the time in sources files, if not always. And i would strongly discourage you to do this in header files.
It's easier to just put your tests in separate files, only linking them when needed.
Yup, as others say, you're misusing it since you can't compare strings that way in C, and especially not in the preprocessor.
The file that defines int main(int argc, char* argv[]) is the main file. There can be only one such function in an executable.
In addition to what others have said (you can't have the C preprocessor compare strings), be careful with __BASE_FILE__ because it may not correspond to your definition of "main" file. __BASE_FILE__ is the name of the file being compiled, so it's always equal to __FILE__ in source files, and only differs in headers and other included files.
In particular, __BASE_FILE__ is not the name of the file which contains the main() function.
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 < string.h>
#include < stdlib.h>
#include < metal.h>
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.
I am working in existing C code which has a couple of lines with statements similar to this one:
struct collect_conn *tc = (struct collect_conn *)
((char *)c - offsetof(struct collect_conn, runicast_conn));
The struct collect_conn goes along the following lines:
struct collect_conn {
struct runicast_conn runicast_conn;
struct announcement announcement;
const struct collect_callbacks *cb;
struct ctimer t;
uint16_t rtmetric;
uint8_t forwarding;
uint8_t seqno;
};
I am using Eclipse CDT, and it marks the line with an orange squiggly line as 'syntax error'. I think it is marked as such by the CDT indexer.
However, compilation (manually in a terminal) is no problem.
This is a bit inconvenient however, since the elements on the line don't get indexed (so the call hierarchy tree isn't always correct, or the highlighting of elements, etc.)
Why does Ecipse not like the line as it is?
Eclipse CDT contains its own preprocessor/parser for analyzing your code and building an index. However, when you invoke a build CDT calls out to your system compiler, like gcc for example. There may be minor differences between the syntax accepted by the CDT parser and the syntax accepted by your compiler. When this happens the CDT parser can get confused.
On my system the offsetof macro expands into an expression that uses the __offsetof__ keyword. This keyword isn't recognized by CDT so that's why there's a syntax error. To deal with this problem the CDT parser has a macro built in to deal with __offsetof__ which looks like this:
#define __offsetof__(x) (x)
This doesn't appear to be correct, at least on my system the result is the removal of the __offsetof__ keyword from the source which still leads to a syntax error.
I was able to get rid of the syntax error by going to the Paths and Symbols property page and adding a macro for __offsetof__ which maps to 'foo'. This tricks the parser into thinking its just a call to a function it hasn't seen before, but not a syntax error.
Alternatively you can turn off syntax error reporting in the editor by going to Window > Preferences > General > Editors > Text Editors > Annotations and unchecking all the checkboxes for C/C++ Indexer Markers.
I've fixed problem in eclipse CDT with Preferences->C/C++->Language Mappings : Add
Content Type : C-header
Language : C++
Sometimes, although the code compiles with no error, eclipse CDT's real-time code analyzer shows some errors in C/C++ files (eg. 'Function xxx could not be resolved). This is because eclipse CDT uses its own preprocessor/parser for analyzing the code and building the indexes instead of the MinGW's one (or any other GNU compiler). In order to fix this globally for all eclipse projects in the workspace, follow these steps:
(In order to fix this only for a specific project, follow steps 1, 2 and 4 in menu 'Project->Preferences')
1-In menu 'Window->Preferences->C/C++->Language Mappings', add the correct mappings as shown in below: (eg. for content types: C++ Source/Header File, use GNU C++ language and so on)
2-In menu 'Window->Preferences->C/C++->Indexer', set full indexing by checking all checkboxes (but not 'Skip' ones) as shown in below:
3-In each project's specific properties, menu 'Project->Properties->C/C++ general->Indexer', Uncheck 'Enable project specific settings' as shown in below:
4-Rebuild the indexing, menu 'Project->C/C++ Index->Rebuild'.
It seems the CDT parser doesn't like the portion offsetof(struct ...).
If you declare collect_conn using a typedef the error goes away. At least for me, the following code works:
typedef struct {
struct runicast_conn runicast_conn;
struct announcement announcement;
const struct collect_callbacks *cb;
struct ctimer t;
uint16_t rtmetric;
uint8_t forwarding;
uint8_t seqno;
} collect_conn;
...
struct collect_conn *tc = (struct collect_conn *)
((char *)c - offsetof(collect_conn, runicast_conn));
If you can't change the original declaration do something like this:
typedef struct collect_conn collect_conn_t;
It might be confused, check if you have a definition of offsetof in-scope, for instance. Otherwise you might try simplifying the expression, breaking it up using e.g. a #define with the offset of, or something.
I'm thinking the compiler might provide a built-in version of offsetof, while Eclipses's compiler/code-parser might not. If so, you would need to make sure you have the definition, for Eclipse to be able to properly parse your code.
try switching the indexer to "Full c/C++ indexer (complete parse)" in Preferences->c/C++ -> indexer
Iv got the same problem. There is 2 definition of offsetof (one for C and one for C++). IMO the problem come from that
For example if i type
#ifndef __cplusplus
#endif
Eclipse will grey it. It mean __cplusplus is defined, but my project is a C
Unfortunatly i dont find a fix.
I fixed similar problem after checking the tab Error Parsers in Makefile Project in New CDT Project Wizard, removing CDT Visual C Error Parser (I am using gcc)
I ended up solving the problem like this. First I opened the project properties, then the C/C++ general->Paths and Symbols category. Under the Symbols tab I added this entry:
Symbol: offsetof(TYPE,MEMBER)
Value: ((ssize_t) &((TYPE *)0)->MEMBER)
These symbols are used by the indexer but not passed to the compiler (at least in Makefile projects, I haven't tried it in the other kind of C project), so it doesn't override GCC's built-in offsetof
I've seen Eclipse do this some times, and I use it for Java. Usually closing and opening the file again fixes it for me (resets whatever is wrong). It usually seems to be an error that WAS there but has been fixed and the "error cache" isn't updated correctly.