force gcc compilation / ignore error messages - c

I'm trying to compile some code I found online, but gcc keeps getting me error messages.
Is there any way I can bypass the error, and compile?
ttys000$ gcc -o s-proc s-proc.c
s-proc.c:84:18: error: \x used with no following hex digits
Here's the line it keeps bitching about:
printf("\x%02x", ((unsigned char *)code)[i]);
...
First post on here, so if I broke any rules or wasn't specific enough, let me know.

You can't ignore errors1. You can only ignore warnings. Change the code.
printf("\\x%02x", ((unsigned char *)code)[i]);
It's just a guess, since without documentation or input from the original author of the code, we have no solid evidence for what the code is actually supposed to do. However, the above correction is extremely plausible, it's a simple typo (the original author forgot a \), and it's conceivable that the author uses a C compiler which silently ignores the error (Python has the same behavior by design).
The line of code above, or something almost exactly like it, is found in probably tens of thousands of source files across the globe. It is used for encoding a binary blob using escape sequences so it can be embedded as a literal in a C program. Similar code appears in JSON, XML, and HTML emitters. I've probably written it a hundred times.
Alternatively, if the code were supposed to print out the character, this would not work:
printf("\x%02x", ((unsigned char *)code)[i]);
This doesn't work because escape sequences (the things that start with \, like \x42) are handled by the C compiler, but format strings (the things that start with %, like %02x) are handled by printf. The above line of code might only work if the order were reversed: if printf ran first, before you compiled the program. So no, it doesn't work.
If the author had intended to write literal characters, the following is more plausible:
printf("%c", ((unsigned char *)code)[i]); // clumsy
putchar((unsigned char *)code)[i]); // simpler
So you know either the original author simply typo'd and forgot a single \ (I make that mistake all the time), or the author has no clue.
Notes:
1: An error means that GCC doesn't know what the code is supposed to do, so continuing would be impossible.

Looks like you want to add a prefix of x to the hex number. If yes, you can drop the \:
printf("x%02x", ((unsigned char *)code)[i]);
The reason you are getting error is \x marks the beginning of a hex escape sequence.
Example: printf("\x43\x4f\x4f\x4c");
Prints
COOL
As C has an ASCII value of 0x43.
But in your case the \x is not followed by hex digits which causes parse errors. You can see the C syntax here it clearly says:
hex-escape ::= \x hex-digit ∗

Escape the \ with another \
printf("\\x%02x", ((unsigned char *)code)[i]);
By the way, you can't force GCC to continue compilation after an error, as as error is an error because it prevents further logical analysis of the source code which is impossible to resolve.

Related

Misplaced preprocessor character '\'

I'm trying to get a bunch of C modules written in 1994 for a Panasonic 3DO lib to compile with armcc. I've run into an error which I'm kind of confused about. My knowledge of C is not that deep, so perhaps one of you would be so kind as to help me figure this out:
#define DS_MSG_HEADER \
long whatToDo; /* opcode determining msg contents */ \
Item msgItem; /* message item for sending this buffer */ \
void* privatePtr; /* ptr to sender's private data */ \
void* link /* user defined -- for linking msg into lists */
The \ character is used in many include files in this library I'm unfamiliar with this syntax... and the ARM compiler seems to hate it.
Serious error: misplaced preprocessor character '\'
If you know why these \ characters are being used, could please explain? (Sorry if its a noob question) Also, is there an alternative way to write this so the compiler is happy?
This error is shown (among other reasons) if the shown backslash '\' is not the last character on the line.
I can think of two reasons:
Somehow you got at least one whitespace (space, tab) after the backslash.
I never had this problem.
The source is stored with Windows-style end-of-line markers, that are '\r' and '\n', "carriage return" and "line feed". And you are trying to compile it on a Unix-like system (Linux?) or by a compiler that expects Unix-like end-of-line markers, that is only '\n', "line feed". (Or the other way around.)
This is a quite common problem, that hits me time after time.
In any case, open the source in a capable editor and enable the visibility of "unvisible characters", commonly an option with this icon: ¶. Check for whitespace. Then check for the coding of the end-of-line. Save with the appropriate one.

C - representing binary in #defines

The code snippet below works as is but if I uncomment the first #define and comment the second the compiler complains about expecting a ')' at the assignment statement. Thought it might be wanting a cast but that did not help. Please point out my stupid oversight.
Thanks,
jh
//#define SMI_READ (0b10 << 10)
#define SMI_READ (0x2 << 10)
...
command |= SMI_READ;
In general, to answer a question like this we need to see the complete and unedited text of the error messages, and it also really helps if you provide a complete program that we can attempt to compile for ourselves. (It might seem to you that the error messages are useless, but often it's just that they only make sense if you know how to think like a compiler engineer.)
However, in this case, I can make a high-confidence guess, because the only difference between the two macros is that the one that doesn't work uses a binary number, 0b10, and the one that does work uses a hexadecimal number, 0x2. Binary numbers are not part of any version of the C standard, although they are a common extension. I therefore deduce that your compiler doesn't support them and is giving an unclear error message when it encounters them.
From C standard (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)
6.4.4.1 Integer constants
...
octal-constant:
0
octal-constant octal-digit
...
hexadecimal-prefix: one of
0x 0X
No other prefixes are described, especially nothing which would cover 0b10.

What does '\' actually do in C?

As far as I know \ in C just appends the next line as if there was not a line break.
Consider the following code:
main(){\
return 0;
}
When I saw the pre-processed code(gcc -E) it shows
main(){return
0;
}
and not
main(){return 0;
}
What is the reason for this kind of behaviour? Also, how can I get the code I expected?
Yes, your expected result is the one required by the C and C++ standards. The backslash simply escapes the newline, i.e. the backslash-newline sequence is deleted.
GCC 4.2.1 from my OS X installation gives the expected result, as does Clang. Furthermore, adding a #define to the beginning and testing with
#define main(){\
return 0;
}
main()
yields the correct result
}
{return 0;
Perhaps gcc -E does some extra processing after preprocessing and before outputting it. In any case, the line break seen by the rest of the preprocessor seems to be in the right place. So it's a cosmetic bug.
UPDATE: According to the GCC FAQ, -E (or the default setting of the cpp command) attempts to put output tokens in roughly the same visual location as input tokens. To get "raw" output, specify -P as well. This fixes the observed issues.
Probably what happened:
In preserving visual appearance, tokens not separated by spaces are kept together.
Line splicing happens before spaces are identified for the above.
The { and return tokens are grouped into the same visual block.
0 follows a space and its location on the next line is duly noted.
PLUG: If this is really important to you, I have implemented my own preprocessor with correct implementation of both raw-preprocessed and whitespace-preserving "pretty" modes. Following this discussion I added line splices to the preserved whitespace. It's not really intended as a standalone tool, though. It's a testbed for a compiler framework which happens to be a fully compliant C++11 preprocessor library, which happens to have a miniature command-line driver. (The error messages are on par with GCC, or Clang, sans color, though.)
From K&R section A.12 Preprocessing:
A.12.2 Line Splicing
Lines that end with the backslash character \ are
folded by deleting the backslash and the following newline character.
This occurs before division into tokens.
It doesn't matter :/ The tokenizer will not see any difference. 1
Update In response to the comments:
There seems to be a fair amount of confusion as to what the expected output of the preprocessor should be. My point is that the expectation /seems/ reasonable at a glance but doesn't actually need to be specified in this way for the output to be valid. The amount of whitespace present in the output is simply irrelevant to the parser. What matters is that the preprocessor should treat the continued line as one line while interpreting it.
In other words: the preprocessor is not a text transformation tool, it's a token manipulation tool.
If it matters to you, you're probably
using the preprocessor for for something other than C/C++
treating C++ code as text, which is a ... code smell. (libclang and various less complete parser libraries come to mind).
1 (The preprocessor is free to achieve the specified result in whichever way it sees fit. The result you are seeing is possibly the most efficient way the implementors have found to implement this particular transformation)

Why pre-processor gives a space?

I want to comment a line using the pre-processor:
#define open /##*
#define close */
main()
{
open commented line close
}
when I do $gcc -E filename.c I expected
/* commented line */
but I got
/ * commented line */
so that the compiler shows an error
Why it is giving an unwanted space ?
From the GNU C Preprocessor documentation:
However, two tokens that don't together form a valid token cannot be pasted together. For example, you cannot concatenate x with + in either order. If you try, the preprocessor issues a warning and emits the two tokens. Whether it puts white space between the tokens is undefined. It is common to find unnecessary uses of '##' in complex macros. If you get this warning, it is likely that you can simply remove the '##'.
In this case '*' and '/' do not form a valid C or C++ token. So they are emitted with a space between them.
(Aside: you are likely to get C compilation errors even if you do manage to insert "comments" into the output of the C preprocessor. There aren't supposed to be any comments there.)
The error is because /* is not a valid token.
As explained from the CPP doc:
two tokens that don't together form a valid token cannot be pasted together. For example, you cannot concatenate x with + in either order.
You can get the error by pasting other nonsense stuff e.g. /##+ or +##-.
About the space, it is deliberately inserted to avoid creating a comment and mess up the rest. From the GCC source code:
/* Avoid comment headers, since they are still processed in stage 3.
It is simpler to insert a space here, rather than modifying the
lexer to ignore comments in some circumstances. Simply returning
false doesn't work, since we want to clear the PASTE_LEFT flag. */
if ((*plhs)->type == CPP_DIV && rhs->type != CPP_EQ)
*end++ = ' ';
The preprocessor runs and produces code in a form that the C compiler can understand. It only processes your code once, so even if you could produce a /* with your #define, the compiler would see the /* and give you an error because it's not valid C code (it's a preprocessing instruction).
This doesn't seem like a very good thing to do.
Because comments are replaced with spaces before (and only before) the preprocessor runs. If you paste together the characters / and * using the preprocessor, you get /* which is just a couple operators. Edit: such abuse of ## technically creates /* as a single token, which has undefined behavior. You can paste together > ## > or < %:%: :, although you shouldn't.
See §6.4.6 of C99 for what tokens you are allowed to construct and 6.10.3.3 for the catenation process.
If you want to comment some code using pre-processor, use
#if 0
...
#endif

C char array is not a string pattern?

I am having a compilation error on the following code:
printf((char *) buffer);
and the error message that I am getting is:
cc1: format not a string literal and no format arguments...
I suspect there are some libraries that I forgot to install, as I was able to compile and run the code without an error on the other machine...
PS: The question rises with the fact that I was able to run the same code on some other machine... I suspect a difference in gcc version might cause a problem like this?
Newer GCC versions try to parse the format string passed to printf and similar functions and determine if the argument list correctly matches the format string. It can't do this because you've passed it a buffer for the first argument, which would normally be a format string.
Your code is not incorrect C, it's just a poor usage of C. As others mentioned you should use "%s" as a format string to print a single string. This protects you from a class of errors that involve percentage signs in your string, if you don't control the input. It's a best practice to never pass anything but a string literal as the first argument to the printf or sprintf family of functions.
try
printf("%s", (char*) buffer);
;-)
This warning is generated by gcc if
-Wformat-nonliteral
is set. It's not part of -Wall or -Wextra (at least for version 4.4.0), so just drop it if you want the code to compile warning-free.
This is a warning for your safety, not an error. This new compiler is apparently being more strict about it. I don't think it's actually illegal in C, so the compiler should have an option to disable treating this as an error.
However, you pretty much never want to pass anything other than a string literal as the first argument to printf. The reason that doing so is such a horrible idea that the compiler has a special built-in check to warn you about it is this: Suppose the non-literal string that you pass as the first argument to printf happens to contain printf formatting characters. printf is then going to try to access second, third, fourth, etc, arguments that you didn't actually pass in, and may well crash your program by trying to do so. If the non-literal first argument is actually user-supplied, then the problem is even worse since a malicious user could crash your program at will.

Resources