Is there a way to safely check to see whether some named variable (let's call it "foo") is present in the current scope? I'd like to have a macro that, say, makes use of "foo" if it's present, otherwise does something else. Are there any runtime tricks I can make use of here?
(The actual context is trying to solve this problem, but I realized that one could be a special case of this one, so a separate question seemed also interesting.)
Unfortunately, no. The compiler is responsible for parsing variable names and assigning scopes to them, and the preprocessor runs before the compiler. So it has no access to that information.
Related
Can a function tell what's calling it, through the use of memory addresses maybe? For example, function foo(); gets data on whether it is being called in main(); rather than some other function?
If so, is it possible to change the content of foo(); based on what is calling it?
Example:
int foo()
{
if (being called from main())
printf("Hello\n");
if (being called from some other function)
printf("Goodbye\n");
}
This question might be kind of out there, but is there some sort of C trickery that can make this possible?
For highly optimized C it doesn't really make sense. The harder the compiler tries to optimize the less the final executable resembles the source code (especially for link-time code generation where the old "separate compilation units" problem no longer prevents lots of optimizations). At least in theory (but often in practice for some compilers) functions that existed in the source code may not exist in the final executable (e.g. may have been inlined into their caller); functions that didn't exist in the source code may be generated (e.g. compiler detects common sequences in many functions and "out-lines" them into a new function to avoid code duplication); and functions may be replaced by data (e.g. an "int abcd(uint8_t a, uint8_t b)" replaced by a abcd_table[a][b] lookup table).
For strict C (no extensions or hacks), no. It simply can't support anything like this because it can't expect that (for any compiler including future compilers that don't exist yet) the final output/executable resembles the source code.
An implementation defined extension, or even just a hack involving inline assembly, may be "technically possible" (especially if the compiler doesn't optimize the code well). The most likely approach would be to (ab)use debugging information to determine the caller from "what the function should return to when it returns".
A better way for a compiler to support a hypothetical extension like this may be for the compiler to use some of the optimizations I mentioned - specifically, split the original foo() into 2 separate versions where one version is only ever called from main() and the other version is used for other callers. This has the bonus of letting the compiler optimize out the branches too - it could become like int foo_when_called_from_main() { printf("Hello\n"); }, which could be inlined directly into the caller, so that neither version of foo exists in the final executable. Of course if foo() had other code that's used by all callers then that common code could be lifted out into a new function rather than duplicating it (e.g. so it might become like int foo_when_called_from_main() { printf("Hello\n"); foo_common_code(); }).
There probably isn't any hypothetical compiler that works like that, but there's no real reason you can't do these same optimizations yourself (and have it work on all compilers).
Note: Yes, this was just a crafty way of suggesting that you can/should refactor the code so that it doesn't need to know which function is calling it.
Knowing who called a specific function is essentially what a stack trace is visualizing. There are no general standard way of extracting that though. In theory one could write code that targeted each system type the software would run on, and implement a stack trace function for each of them. In that case you could examine the stack and see what is before the current function.
But with all that said and done, the question you should probably ask is why? Writing a function that functions in a specific way when called from a specific function is not well isolated logic. Instead you could consider passing in a parameter to the function that caused the change in logic. That would also make the result more testable and reliable.
How to actually extract a stack trace has already received many answers here: How can one grab a stack trace in C?
I think if loop in C cannot have a condition as you have mentioned.
If you want to check whether this function is called from main(), you have to do the printf statement in the main() and also at the other function.
I don't really know what you are trying to achieve but according to what I understood, what you can do is each function will pass an additional argument that would uniquely identify that function in form of a character array, integer or enumeration.
for example:
enum function{main, add, sub, div, mul};
and call functions like:
add(3,5,main);//adds 3 and 5. called from main
changes to the code would be typical like if you are adding more functions. but it's an easier way to do it.
No. The C language does not support obtaining the name or other information of who called a function.
As all other answers show, this can only be obtained using external tools, for example that use stack traces and compiler/linker emitted symbol tables.
This question may be silly.
C standard:(referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared)
What has the localness to the main function of the variables argc and argv got to do with changing their names? — I know that their names can be changed — I didn't understand the statement in the standard with respect to the localness of the variables. Please help me.
"Localness" means that thing that happen inside the scope of "whatever" don't affect the rest of the world. As far as the names of function parameters go, those names are not exposed to outside of the function. What is exposed (to varying degrees depending on implementation and system standards) are the function signatures (aka prototypes).
The term "localness" is not specific to main. Every function has a local scope. So does main. And its parameters of type int and (char*)[] are not visibly by name to the outside world.
What has the localness to the main function of the variables argc and
argv got to do with changing their names? — I know that their names
can be changed — I didn't understand the statement in the standard
with respect to the localness of the variables.
I think you're just overlooking the obvious. The question that the standard is trying to address there is "do I need to use the names argc and argv for the parameters of main()?" I think I've actually seen that question posed here on SO, though I wasn't able to find it in a quick search. You seem to be assuming that of course you can name the parameters whatever you want, on account of them being function parameters. The provision you ask about does nothing but affirm exactly that.
I guess you don't appreciate how someone reading the standard might take away a different impression, and you seem especially to have been thrown by the standard naming main specifically. This is all wrapped up in the facts that main is the one and only function that the standard specifies a program (as opposed to the C implementation) must supply, and that the standard designates two specific options for main's signature from which the programmer must choose. No variation from those is possible if the program is to exhibit strict conformance with the language specification. The provision you ask about just clarifies that using different parameter names does not constitute a meaningful change to the signature for this purpose.
I am passed in a C file. The C file contains functions which contain local variables. Given any C file, i have to be able to find the local variables within a specific method (which the user specifies) and make them global. (specifications for another application which can only handle global variables)...
What is the easiest way to do this? Would it be through shell scripting or should it directly in C. Should i use regex? Am i thinking about doing this the wrong way?
Any help would be appreciated
You are looking for a specific context of variables, in your case the context is local variables declared inside of a function. A regular expression can be used to pull out a function definition, but some kind of token parser would be much better.
Using a simplified grammar for C it can be found that you can get the function strings themselves and from there you can find the local variables themselves.
But, if the C code passed in is in a specific format, IE local variables are at the top of the function definition then a simple regular expression can be used.
C99 will allow variables to be declared throughout the function, within blocks etc., so the task of identifying them is complicated. It might be possible to leverage a lexer/parser like yacc and flex to tokenise a C source file, then pull the variable declarations out of the generated structures. Making this general purpose is likely to be a lot of work.
How can I pass one aditional parameter (not the token minor of type YYSTYPE) to the yypush_parse() function?
The parser is indeed reentrant, but this one aditional variable is crucial for the thread-safety of the application I need to integrate my parser in (it's a PHP extension, so we're talking about TSRM).
I cannot just get rid of that parameter because inside the action code I'm going to call functions which will generate an AST in a userland-accessible form.
I've tried to hack around YYPUSH_DECLS and it works as far as declaring the function is concerned, BUT a few thousand LOCs down comes the implementation of yypush_parse, and I can't see any way to overwrite the function signature where the implementation of yypush_parse starts.
YYPARSE_PARAM is only used when the parser is not a push one (as far as I can tell), but in my case I NEED it be push because of the things I have to do in the processing loop, after lexing and prior to adding a new token to the parsing stack.
So I am wondering if there's a %directive or something that may help.
On the other side, I really think YYPARSE_PARAM should be used as far as it's defined, no matter what type of parser it is. It's a pity it's not.
%parse-param. YYPARSE_PARAM is deprecated and shouldn't be used.
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_