My code looks something like this
while(!eof)
{
if(A)
doSomething;
if(B)
doSomething;
}
A and B are parameters from comand line. There may be also more parameters. I have struct of Bools, in which are all posible parameters and for every parameter, it determines if he exist or not.
Can i make compiler to not read the some part of the code?
I mean, in this code he will check for existence of B every iteration. What i want to achieve is that he will only check once
if(B)
doSomething;
I want this just to optimalize my program and i NEED to have both ifs in one cycle.
Frankly speaking, Ignoring part of code after compilation makes no sense. The code is already compiled. However. you can skip the execution of certain part of code using conditional statements, like if, else-if etc.
FWIW, "Command line parameters" are supplied and considered at run-time. There is no way you can decide (conditional compilation) based on that at compile-time.
However, if you want, you can always check the number of arguments (argc) supplied through command line and take action based on that.
Alternatively, if you wanted to have a conditional compilation, reading something about #ifdef/#ifndef may help.
Related
I have the following fragment in my Bison file that describes a simple "while" loop as a condition followed by a sequence of statements. The list of statements is large and includes BREAK and CONTINUE. The latter two can be used only within a loop.
%start statements
%%
statements: | statement statements
statement: loop | BREAK | CONTINUE | WRITE | ...
loop: WHILE condition statements ENDWHILE
condition: ...
%%
I can add a C variable, set it upon entering the loop, reset it upon exiting, and check at BREAK or CONTINUE, but this solution does not look elegant:
loop: WHILE {loop++;} condition statements {loop--;} ENDWHILE
statement: loop | BREAK {if (!loop) yyerror();} ...
Is there a way to prevent the two statements from outside a loop using only Bison rules?
P.S. What I mean is "Is there an EASY way..," without fully duplicating the grammar.
Sure. You just need three different statement non-terminals, one which matches all statements; one which matches everything but continue (for switch blocks), and one which matches everything but break and continue. Of course, this distinction needs to trickle down through your rules. You'll also need three versions of each type of compound statement: loops, conditionals, switch, braced blocks, and so on. Oh, and don't forget that statements can be labelled, so there are some more non-terminals to duplicate.
But yeah, it can certainly be done. The question is, is it worth going to all that trouble. Or, to put it another way, what do you get out of it?
To start with, the end user finds that where they used to have a pretty informative error message about continue statements outside a loop, they now just get a generic Syntax Error. Now, you can fix that with some more grammar modifications, by actually providing productions which match the invalid statements, and then present a meaningful error message. But that's almost exactly the same code already rejected as inelegant.
Other than that, does it in any way reduce parser complexity? It lets you assume that a break statement is legally placed, but you still have to figure out where the break statement's destination. And other than that, there's not really a lot of evident advantages, IMHO.
But if you want to do it, go for it.
Once you've done that, you could try modifying your grammar so that break, continue, goto and return cannot be followed by an unlabelled statement. That sounds like a good idea, and some languages do it. It can certainly be done in the grammar. (But before you get too enthusiastic, remember that some programmers do deliberately create dead code during debugging sessions, and they won't thank you for making it impossible.)
There is a BNF extension, used in the ECMAscript standard, amongst others, which parameterizes non-terminals with a list of features, each of which can be present or not. These parameters can then be used in productions, either as conditions or to be passed through to non-terminals on the right-hand side. This could be used to generate three versions of statement, using the features [continue] and [break], which would be used as gates on those respective statement syntaxes, and also passed through to the compound statement non-terminals.
I don't know of a parser generator capable of handling such parameterised rules, so I can't offer it as a concrete suggestion, but this question is one of the use cases which motivated parameterised non-terminals. (In fact, I believe it's one of the uses, but I might be remembering that wrong.)
With an ECMAScript-style formalism, this grammatical restriction could be written without duplicating rules. The duplication would still be there, under the surface, since the parser generator would have to macro expand the templated rules into their various boolean possibilities. But the grammar is a lot more readable and the size of the state machine is not so important these days.
I have no doubt that it would be a useful feature, but I also suspect that it would be overused, with the result that the quality of error messages would be reduced.
As a general rule, compilers should be optimised for correct inputs, with the additional goal of producing helpful error messages for invalid input. Complicating the grammar even a little to make easily described errors into syntax errors does not help with either of these goals. If it's possible to write a few lines of code to produce the correct error message for a detected problem, instead of emitting a generic syntax error, I would definitely do that.
There are (many) other use cases for the ECMAScript BNF extensions. For example they make it much easier to describe a syntax whose naive grammar requires two or three lookahead tokens.
I'm writing unit tests for some function macros, which are just wrappers around some function calls, with a little housekeeping thrown in.
I've been writing tests all morning and I'm starting to get tedium of the brainpan, so this might just be a case of tunnel vision, but:
Is there a valid case to be made for unit testing for macro expansion? By that I mean checking that the correct function behavior is produced for the various source code forms of the function macro's arguments. For example, function arguments can take the form, in source code of a:
literal
variable
operator expression
struct member access
pointer-to-struct member access
pointer dereference
array index
function call
macro expansion
(feel free to point out any that I've missed)
If the macro doesn't expand properly, then the code usually won't even compile. So then, is there even any sensible point in a different unit test if the argument was a float literal or a float variable, or the result of a function call?
Should the expansion be part of the unit test?
As I noted in a comment:
Using expressions such as value & 1 could reveal that the macros are careless, but code inspections can do that too.
I think going through the full panoply of tests is overkill; the tedium is giving you a relevant warning.
There is an additional mode of checking that might be relevant, namely side-effects such as: x++ + ++y as an argument. If the argument to the macro is evaluated more than once, the side-effects will probably be scrambled, or at least repeated. An I/O function (getchar(), or printf("Hello World\n")) as the argument might also reveal mismanagement of arguments.
It also depends in part on the rules you want to apply to the macros. However, if they're supposed to look like and behave like function calls, they should only evaluate arguments once (but they should evaluate each argument — if the macro doesn't evaluate an argument at all, then the side-effects won't occur that should occur (that would occur if the macro was really a function).
Also, don't underestimate the value of inline functions.
Based on the comments and some of the points made in #Jonathan Leffler's answer, I've come to the conclusion that this is something that is better tested in functional testing, preferably with a fuzz tester.
That way, using a couple of automation scripts, the fuzzer can throw a jillion arguments at the function macro and log those that either don't compile, produce compiler warnings, or compile and run, but produce the incorrect result.
Since fuzz tests aren't supposed to run quickly (like unit tests), there's no problem just adding it to the fuzz suite and letting it run over the weekend.
The goal of testing is to find errors. And, your macro definitions can contain errors. Therefore, there is a case for testing macros in general, and unit-testing in particular can find many specific errors, as will be explained below.
Code inspection can obviously also be used to find errors, however, there are good points in favor of doing both: Unit-tests can cheaply be repeated whenever the respective code is modified, say, for reactoring.
Code inspections can not cheaply be repeated (at least they cause more effort than re-running unit-tests), but they also can find other points that tests can never detect, like, wrong or bad documentation, design issues like code duplication etc.
That said, there are a number of issues you can find when unit-testing macros, some of which were already mentioned. And, it may in principle be possible that there are fuzz testers which also check for such problems, but I doubt that problems with macro definitions are already in focus of fuzz-testers:
wrong algorithm: Expressions and statements in macro definitions can just be as wrong as they can be in normal non-macro code.
unsufficient parenthesization (as mentioned in the comments): This is a potential problem with macros, and it can be detected, possibly even at compile time, by passing expressions with operators with low precedence as macro arguments. For example, calling FOO(x = 2) in test code will lead to a compile error if FOO(a) is defined as (2 * a) instead of (2 * (a)).
unintended multiple use of arguments in the expansion (as mentioned by Jonathan): This also is a potential problem specific to macros. It should be part of the specification of a macro how often its arguments will be evaluated in the expanded code (and sometimes there can no fixed number be given, see assert). Such statements about how often an argument will be evaluated can be tested by passing macro arguments with side effects that can afterwards be checked by the test code. For example, if FOO(a) is defined to be ((a) * (a)), then the call FOO(++x) will result in x being incremented twice rather than once.
unintended expansion: Sometimes a macro shall expand in a way that causes no code to be produced. assert with NDEBUG is an example here, which shall expand such that the expanded code will be optimized away completely. Whether a macro shall expand in such a way typically depends on configuration macros. To check that a macro actually 'disappears' for the respective configuration, syntactically wrong macro arguments can be used: FOO(++ ++) for example can be a compile-time test to see if instead of the empty expansion one of the non-empty expansions was used (whether this works, however, depends on whether the non-empty expansions use the argument).
bad semicolon: to ensure that a function like macro expands cleanly into a compound statement (with proper do-while(0) wrapper but without trailing semicolon), a compile time check like if (0) FOO(42); else .. can be used.
Note: Those tests I mentioned to be compile-time tests are, strictly speaking, just some form of static analysis. In contrast to using a static analysis tool, such tests have the benefit to specifically test those properties that the macros are expected to have according to their design. Like, static analysis tools typically issue warnings when macro arguments are used without parentheses in the expansion - however, in many expansions parentheses are intentionally not used.
Is there a C macro, a GCC directive or pragma, to consume the next code statement following the macro, without explicitly passing it as an argument to the macro?
Something like this:
#define CONSUME_NEXT_IF(a) if (a) { (<next>) } else;
And I would use it as:
CONSUME_NEXT_IF(a) stmt1;
And expect it to expand to:
if (a) stmt1;
else;
I am using an if statement here just as an example. The conditional statement isn't the point, rather the ability to consume stmt1 by the macro without actually passing it as an argument.
#define CONSUME_NEXT_IF(a) if (!(a)) {} else
will achieve the effect of only executing the "next statement" (between use of the macro and next ;) if a is true (or non-zero). If you have suitable constraints on what type of expression a is, you might be able to remove the () on (a).
Personally, although you've explained in comments that you want a similar effect to annotations, I consider this will introduce more maintenance concerns - including code obfuscation - than it alleviates. Particularly if it interacts with other macros being used in a or stmt1.
And, of course, it would be necessary to modify your "large code base" to use the macro.
This also leaves dead code in your executable - it doesn't stop code for stmt1 being emitted to the executable (unless a has a fixed compile-time value, and your compiler has capability to detect and optimise code in such circumstances). Therefore such a construct will mean you cannot satisfy requirements of several assurance standards that require prevention of dead code.
For example, there is the source:
void func1() {
func3();
if(qqq) {
func2();
}
func4(
);
}
It should be transformed to:
void func1() {
MYMACRO
func3();
MYMACRO
if(qqq) {
MYMACRO
func2();
MYMACRO
}
MYMACRO
func4(
);
MYMACRO
}
I.e. to insert "MYMACRO\n" at the end of each line where statement can be, only inside functions.
How to do it easily? Should I use regular expressions? What tools should I use?
For example, can gcc output all line numbers of all statement begins (or ends) inside functions?
#related How to tell gcc to instrument the code with calls to my own function each _line_ of code?
#related What profiler should I use to measure _real_ time (including waiting for syscalls) spend in this function, not _CPU_ one
What are you trying to accomplish by doing this? Based on the description of the task, there is probably a much easier way to approach the problem. If you're sure that this is the best way to accomplish your task, read on.
You would have to implement some sort of rudimentary C language parser to do this. Since you are processing text, I would recommend using a scripting language like perl, python, or ruby to modify your text instead of writing a C program to do it.
Your parser will walk through the file a line at a time and for each line, it will determine whether it needs to insert your macro. The parser will need to keep track of a number of things. First, it needs to keep track of whether or not it is currently inside of a comment. When you encounter a /* sequence, set a "in comment" flag and clear it the next time you encounter a */ sequence. Whenever that flag is set, you will not add a macro invocation. Also, you will need to keep track of whether or not you are inside a function. Assuming your code is fairly simple and straightforward, you can have a "brace counter" that starts at zero, increments whenever you encounter a {, and decrements whenever you encounter a }. If your brace counter is zero, then you are not inside of a function and you shouldn't add a macro call. You will also want to add special code to detect and ignore braces that are part of a structure definition, array initializer, etc. Note that simple brace counting won't work if your code does more complicated things like:
void some_function (int arg) {
#ifdef CHECK_LIMIT_ONLY
if (arg == 0) {
#else
if (arg < 10) {
#endif
// some code here
...
}
}
While you could argue that snippet is simply a case of poorly-written code, it's just an example of the type of problem that you can run into. If your code has something in it that breaks simple brace counting, then this problem just got significantly more difficult. One way to tell if your code will break brace counting is if you reach the end of the file with a non-zero brace count or if at any point in time the brace count goes negative.
Once you can determine when you are in a function and not in a comment, you need to determine whether the line needs a macro inserted after it. You can start with a few simple rules, test the script, and see if there are any cases that it missed. For starters, any line ending in a semicolon is the end of a statement and you will want to insert a macro after it. Similar to counting braces, when you are inside of a function you will want to count parenthesis so that you can determine if you are inside of a function call, loop conditional, or other compound statement. If you are inside one of these, you will not add the macro. The other code location to track is the the start and end lines of a { ... } block. If a line ends in { or }, you will add a macro after it.
For a complicated task like this, you will definitely want to script something up, try it out on a relatively simple piece of code, and see what it gets wrong. Make adjustments to cover the cases you missed the first time and re-test. When it can parse the simple code correctly, give it something more complicated and see how well it does.
''Update:'' To address the concerns that some people have expressed regarding the additional latency of adding print commands, remember that you don't have to print a timestamp at every macro call. Instead, have the macro call grab a timestamp and stick it onto a list. Once your program is done, print all the timestamps off of the list. That way, you save all the print-related delay until after your test is over.
rewrite your sources so the following works :-)
Instead of gcc ... file1.c file2.c ... do
gcc ... `sed -e's/;/;\nMYMACRO/' file1.c` file1extra.c \
`sed -e's/;/;\nMYMACRO/' file2.c` file2extra.c \
...
Here's some quick and dirty C# code. Basically just primitive file IO stuff. It's not great, but I did whip it up in around 3 minutes. This code implies that function blocks are demarcated with a comment line of "//FunctionStart" at the beginning and "//FunctionEnd" at the end. There are more elegant ways of doing this, this is the fast/dirty/hacky approach.
Using a managed app to do this task is probably overkill, but you can do a lot of custom stuff by simply adding on to this function.
private void InsertMacro(string filePath)
{
//Declrations:
StreamReader sr = new StreamReader(filePath);
StreamWriter sw = new StreamWriter(filePath + ".tmp");
string line = "";
bool validBlock = false;
//Go through source file line by line:
while ((line = sr.ReadLine()) != null)
{
if (line == "//FunctionStart")
validBlock = true;
else if (line == "//FunctionEnd")
validBlock = false;
sw.WriteLine(line);
if (validBlock)
sw.WriteLine("MYMACRO");
}
//Replace legacy source with updated source:
File.Delete(filePath);
File.Move(filePath + ".tmp", filePath);
//Clean up streams:
sw.Close();
sr.Close();
}
Calling all C macro gurus...
Is there any way to write a C macro that will replace something like this:
my_var = 5;
with this:
setVar(&my_var, 5);
In other words, can I write a C macro that will override assignments for a specific variable (in the above example, my_var) and instead pass it to a function whose job it is to set that variable? If possible, I'd like to be able to hook into assignments of a specific variable.
EDIT: After thinking about this some more, I'm not sure it could be done. Even if you can come up with a macro to do it, setVar wouldn't necessarily know the type of the variable its setting, so what would be the type of its second argument?
EDIT: The reason I'd like to hook assignments of specific variables is for use in a primitive debugger for some specialized embedded C code. It would be nice to be able to have a "watch list", essentially like you have in an IDE. My first instinct was to try to hook variable assignments with a C macro so you could just drop the macro into your code and have that variable "watched", but then again I've never really written a debugger before so maybe I'm going about that all wrong.
Not with the standard preprocessor. It cannot change the parsing of the file, only replace proper names with a piece of code (and "=" isn't valid in a name).
If you're feeling adventurous, you can try to replace the executable "cpp" with a small script which pre-processes the source code. But that might wreck havoc with the debugging information (file name and, if you're replacing one line of code with several, with line number information, too). The script would call "sed"`:
sed -e 's/my_var\s*=\s*([^;]+);/MY_VAR(my_var, $1);/' file.c > file_tmp.c
But your best bet is probably to put this into a script and simply run it on all your sources. This will change the code and you'll see what is happening in your debugger.
#define setVar(_left_, _right_) *(_left_) = _right_