Search and replace a string as shown below - c

I am reading a file say x.c and I have to find for the string "shared". Once the string like that has been found, the following has to be done.
Example:
shared(x,n)
Output has to be
*var = &x;
*var1 = &n;
Pointers can be of any name. Output has to be written to a different file. How to do this?
I'm developing a source to source compiler for concurrent platforms using lex and yacc. This can be a routine written in C or if u can using lex and yacc. Can anyone please help?
Thanks.

If, as you state, the arguments can only be variables and not any kind of other expressions, then there are a couple of simple solutions.
One is to use regular expressions, and do a simple search/replace on the whole file using a pretty simple regular expression.
Another is to simply load the entire source file into memory, search using strstr for "shared(", and use e.g. strtok to get the arguments. Copy everything else verbatim to the destination.

Take advantage of the C preprocessor.
Put this at the top of the file
#define shared(x,n) { *var = &(x); *var1 = &(n); }
and run in through cpp. This will include external resources also and replace all macros, but you can simply remove all #something lines from the code, convert using injected preprocessor rules and then re-add them.
By the way, why not a simple macro set in a header file for the developer to include?
A doubt: where do var and var1 come from?
EDIT: corrected as shown by johnchen902

When it comes to preprocessor, I'll do this:
#define shared(x,n) (*var=&(x),*var1=&(n))
Why I think it's better than esseks's answer?
Suppose this situation:
if( someBool )
shared(x,n);
else { /* something else */ }
In esseks's answer it will becomes to:
if( someBool )
{ *var = &x; *var1 = &n; }; // compile error
else { /* something else */ }
And in my answer it will becomes to:
if( someBool )
(*var=&(x),*var1=&(n)); // good!
else { /* something else */ }

Related

How to implement Go's defer() in C so that it allows declaring vars?

In this Modern C video there's a trick that allows to postpone execution of a code until the block/scope exits. It's used as follows:
int main()
{
int foo=0, bar;
const char *etc = "Some code before defer";
defer(profile_begin(), profile_end())
{
/* Some code, which will be automatically
* preceded by call to profile_begin() and
* followed by run of profile_end().*/
foo++;
bar = 1;
}
etc = "Some code after defer";
foo = bar + 1;
}
Implementation from the video:
#define macro_var_line(name) concat(name, __LINE__)
#define defer(start,end) for( \
int macro_var_line(done) = (start,0); \
!macro_var_line(done); \
(macro_var_line(done) += 1), end)
It's pretty simply implemented. What might be confusing is the macro_var_line(name) macro. Its purpose is to simply ensure that a temporary variable will have a unique, "obfuscated" name by adding current line number to it (of where defer is called).
However the problem is that one cannot pass code to start snippet that declares new variables, because it is pasted in the for() comma operator that uses int type (the int macro_var_line(done) = …). So it's not possible to, eg.:
defer(FILE *f = fopen("log.txt","a+"), fclose(f))
{
fprintf(f,"Some message, f=%p",f);
}
I would want to have such macro, capable of declaring new vars in start snippet. Is it achievable with standard C99, C11 or maybe some GCC extensions?
UPDATE: I've found a solution utilizing GCC nested functions. Basically, the { bblock } that's following the defer() macro becomes nested function body. And it's possible to forward declare the nested function and invoke it from before the block, i.e.:
#define defer(start,end) \
auto void var_line(routine) (void); \
start; \
/* Invoke above predeclared void routine_123(void) function */ \
var_line(routine)(); \
end; \
/* Define the nested function */ \
void var_line(routine) (void)
UPDATE2: Here's an elegant version which:
runs first leading statements as start and the last one as the end code,
runs the very first statement in its own for()/declarative space,
runs the block properly via an if(cond == 0) check/block start up.
#define defer(...) \
for (int var_line(cond) = 0; var_line(cond) == 0; ) \
for (FIRST_ARG(__VA_ARGS__); var_line(cond) == 0; ) \
for (SKIP_LAST_ARG(SKIP_FIRST_ARG(__VA_ARGS__)); \
var_line(cond) == 0; \
var_line(cond) += 1 ) \
for (int var_line(cond_int) = 0; \
var_line(cond_int) <= 1; \
var_line(cond_int) += 1 ) \
if (var_line(cond_int) == 1) \
{ \
LAST_ARG(__VA_ARGS__); \
} else if (var_line(cond_int) == 0)
As I expressed in comments, my recommendation is to avoid using such a thing in the first place. Whatever your video might have said or implied, the prevailing opinion among modern C programmers is that macro usage should be minimized. Variable-like macros should generally represent context-independent constant values, and function-like macros are usually better implemented as actual functions. That's not to say that all macro use must be avoided, but most modern C professionals look poorly on complex macros, and your defer() is complex enough to qualify.
Additionally, you do yourself no favors by trying to import the style and idioms of other languages into C. The common idioms of each language become established because they work well for that language, not, generally, because they have inherent intrinsic value. I advise you to learn C and the idioms that C programmers use, as opposed to how to write C code that looks like Go.
With that said, let's consider your defer() macro. You write,
However the problem is that one cannot pass code to start snippet that declares new variables
, but in fact the restriction is stronger than that. Because the macro uses the start argument in a comma expression (start,0), it needs to be an expression itself. Declarations or complete statements of any kind are not allowed. That's only indirectly related to that expression appearing in the first clause of a for statement's control block. (The same applies to the end argument, too.)
It may also be important to note that the macro expands to code that fails evaluate the end expression if execution of the associated statement terminates by branching out of the block via a return or goto statement, or by executing a function that does not return, such as exit() or longjmp(). Additionally, unlike with Go's defer, the end expression is evaluated in full after the provided statement -- no part of it is evaluated before, which might surprise a Go programmer. These are characteristics of the options presented below, too.
If you want to pass only the start and end as macro arguments, and you want to allow declarations to appear in start, then you could do this:
// Option 1
#define defer(start,end) start; for( \
int macro_var_line(done) = 0; \
!done; \
(macro_var_line(done) += 1), (end))
That moves start out of the for statement in the macro's replacement text, to a position where arbitrary C code may appear. Do note, however, that any variable declarations will then be scoped to the innermost containing block.
If you want to limit the scope of your declarations then there is also this alternative and variations on it, which I find much more straightforward than the original:
// Option 2
#define defer(start, end, body) { start; body end; }
You would use that like so:
defer(FILE *f = fopen("log.txt","a+"), fclose(f), // argument list continues ...
fprintf(f,"Some message, f=%p",f);
);
That is somewhat tuned to your particular example, in that it assumes that the body is given as a sequence of zero or more complete statements (which can include blocks, flow-control statements, etc). As you can see, it also requires the body to be passed as a macro argument instead of appearing after the macro invocation, but I consider that an advantage, because it facilitates recognizing the point where the deferred code kicks in.
You can simulate defer by using the __attribute__((cleanup(...))) feature of GCC and Clang. Also see this SO question about freeing a variable.
For instance:
// the following are some utility functions and macros
#define defer(fn) __attribute__((cleanup(fn)))
void cleanup_free(void* p) {
free(*((void**) p));
}
#define defer_free defer(cleanup_free)
void cleanup_file(FILE** fp) {
if (*fp == NULL) { return; }
fclose(*fp);
}
#define defer_file defer(cleanup_file)
// here's our code:
void foo(void) {
// here's some memory allocation
defer_free int* arr = malloc(sizeof(int) * 10);
if (arr == NULL) { return; }
// some file opening
defer_file FILE* fp1 = fopen("file1.txt", "rb");
if (fp1 == NULL) { return; }
// other file opening
defer_file FILE* fp2 = fopen("file2.txt", "rb");
if (fp2 == NULL) { return; }
// rest of the code
}
There is actually an effort in the standard's committee to standardize a defer feature. The paper proposal also comes with a reference implementation. The idea is to propose such a feature that may be implemented with the least compiler magic possible.
If all goes to plan, that feature could even be rebase on lambdas, if we get these into C23 in time.
You could use a trick from "Smart Template Container for C". See link.
#define c_autovar(declvar, ...) for (declvar, *_c_ii = NULL; !_c_ii; ++_c_ii, __VA_ARGS__)
Basically you declare a variable and hijack it's type to form a NULL pointer. This pointer is used as a guard to ensure that the loop is executed only once.
Incrementing NULL pointer is likely Undefined Behavior because the standard only allows to form a pointer pointing just after an object and NULL points to no object. However, it's likely run everywhere.
I guess you could get rid of UB by adding a global variable:
int defer_guard;
And setting the guard pointer to a pointer to defer_guard in the increment statement.
extern int defer_guard;
#define defer_var(declvar, cleanup) \
for (declvar, *_c_ii = NULL; \
!_c_ii; \
_c_ii = (void*)&defer_guard, cleanup)
It will work fine when invoked as:
defer_var(FILE *f = fopen("log.txt","a+"), fclose(f))
{
fprintf(f,"Some message, f=%p",f);
}
EDIT
Actually it is possible to derive a macro that will accept both expression and declaration as start. One must use two for loops instead of one.
#define DEFER(start, end) \
for (int _done = 0; !_done;) \
for (start; !(_done++); end)
int main() {
DEFER(FILE *f = fopen("log.txt","a+"), fclose(f)) {
fprintf(f,"Some message, f=%p", (void*)f);
}
FILE *f;
DEFER(f = fopen("log.txt","a+"), fclose(f)) {
fprintf(f,"Some message, f=%p", (void*)f);
}
return 0;
}

Array of macros in c -- is it possible

I was wondering if it is possible to create something like an array of macros.
I've implemented the following code which works:
struct led_cmds_
{
ioport_pin_t *commands[LED_COUNT] ;
};
struct led_cmds_ the_led_cmd_ ;
void populate() {
the_led_cmd_.commands[0] = SPECIFICPIN(0);
}
and in main:
int main(void)
{
//.....
populate();
LED_On(the_led_cmd_.commands[0]);
}
SPECIFICPIN(x) is macro defined as:
#define SPECIFICPIN(X) (LED##X##_PIN)
What I was hoping for is a way to is a way to do something like this:
#define ioport_pin_t* ARR_LED[LED_COUNT] \
for (int j = 0; j < LED_COUNT; j++) ARR_LED[j] = SPECIFICPIN(j);
and then only need to call the following when I want to use the specific pin
LED_On(ARR_LED[some_number])
when I try to do that I get an ARR_LED undeclared (first use in this function) error.
When I try to call SPECIFICPIN(x) where x is an int iterator in a for loop for example, I get an error saying something like 'LEDx_PIN' undeclared...
You need to work on your terminology. An array of macros is not possible. Macros are no data type, but rather pure text replacement before your program is actually compiled.
I guess " populate an array using macros " is what you want to do. But it is not possible to do that in a compile-time loop - What you seem to want to achieve with your ioport_pin_t macro attempt. Macros do not have the capability to expand to more instances of text elements than you have initially given. There is no such feature as looping at compile time through macro expansions and do repetitive expansion of macros.
Your for loop loops at run-time, while the macro is being expanded at compile-time. Once you have made yourself aware what is done by the preprocessor what is done by the compiler, and what is done at run-time by the finished program, you will see that will not work.
Something like
#define P(X) {(LED##X##_PIN)}
ioport_pin_t *commands[LED_COUNT] = {
P(0), P(1), P(2),......}
#undefine P
Would be the closest thing possible to what you seem to want. Note the main use of the pre-processor is not to save you typing effort - You would be better off using copy & paste in your editor, achieve the same thing and have clearer code.
An array as tofro's answer is the way to go. However in cases that couldn't be solved simply with an array then there's another way with switch
#define SPECIFICPIN(X) (LED##X##_PIN)
void setpin(int pin, int value)
{
switch (pin)
{
case 1:
SPECIFICPIN(1) = value;
doSomething(); // if needed
break;
case x: ...
default: ...
}
}

What does this define mean? #define ASSERT(exp)

I see this code in a C program but i don't understand.
#define ASSERT(exp) if(!(exp)){PutStr("Err\n");}
Please explain and show me how to use it.
Thank you!
You should read about Preprocessor directives in C.
Here we are creating a macro, which gets replaced during compile time with the value which we used to define the macro with.
For eg:
We can use
Assert(<some condition or expression>)
through out your code instead of
if(<some condition or expression>)
{
putStr("Err\n");
}
During compile time, compiler replaces all this Assert with the actual condition.
Firest It is better to change the marco name , like MYASSERT
Then we have:#define MYASSERT(exp) if(!(exp)) {PutStr("Err\n");}
Just think when I malloc a char array , I can use it :
char * mem = malloc(800);
MYASSERT(mem);
It is the same as:
char *mem = malloc(800);
if(!mem)
{PutStr("Err\n");} //well I think you already define PutStr function

how to enter while loop using gdb?

I have a while loop as below.
while (*d++ = *sc++)
As I wish to understand pointers in dept I would like to enter the while loop and understand how the while loop is working with the pointers.
I used step in gdb but it does not go into the while loop completely. Is there any way to get into the while loop and understand the manipulation in every step.
* binds tighter then postfix ++. ++ on the right side will be applied last, so:
while (*d++ = *sc++)
is the same as:
while (*d = *sc)
{
d++;
sc++;
The modification is much better to be traced in gdb.
Update:
Don't code like this OP!
Although it might look cool, and prove you are smart. It's difficult to be parsed by the common human brain and therefore error prone? Which we do not want, do we?
Better go for a more clear alternative like proposed above and let the compiler scramble the code.
Option 1:
Look into the assembly code debugging as suggested by Olaf Dietsche.
Option 2:
Use gcc -S test.c to stop compiler after assembling to see the assembly code of your program. Understanding assembly code might be a little hard. More info here
Option 3:
Rewrite your program to something like
while(1)
{
if(*d++ != *sc++)
{
break;
}
}
So that you can put breakpoints and see the values changing.
An alternative, but identical way to write the code is:
*d = *sc;
while (*d > 0)
{
d++;
sc++;
*d = *sc;
}

Personal Preprocessor Directives

Being a C novice I would like to hear what Macro "define"s developers are using. I've been thinking about putting these in a header to skip verbosity I've become used to:
#define TS_ typedef struct {
#define _TS(x) } x;
#define I(x)_ { int i; for ( i = 1; i <= x; i++ ) {
#define _I } }
Can I add \n \t etc within these macros? As I would like to pass on my sourcecode minus the extra include:
#define TS_ typedef struct {\n
#define _TS(x) } x;\n
#define I(x)_ { int i;\n\tfor ( i = 1; i <= x; i++ ) {\n
#define _I \t}\n}\n
Would these work?
ie: Can I use the proprocessor to replace my sourcecode with my personal include to formatted source without the include ?
Links to good preprocessor tips and tricks also appreciated.
Before you get started, do not use macro names that begin with an underscore - these are reserved for compiler and standard library writers, and must not be used in your own code.
Additionally, I would say that the macros you suggest are all very bad ideas, because they hide from the reader what is going on. The only justification for them seems to be to save you a very small amount of typing. Generally, you should only be using macros when there is no sensible alternative. In this case there is one - simply write the code.
You can put whitespace in by escaping the newline
#define SOMETHING whatever\
This is part of the macro
But as others have said it's not really a great way to to do this.
It would be much better to look into editor macros so you could type the shortcut and have the editor expand it.
You are headed into a wrong path. DO NOT make up your own cpp directives that are unfamiliar to others - this will make your code hard to understand, and at some point maintain.
Try to find some good C code to read - good C code does not use these things, for a good reason.
DON'T DO IT. Nobody else will be able to read your code.
As a cautionary example, check out Steve Bourne's original sources for the Bourne shell, where he used macros to write the code in a kind of pidgin Algol style.
You could do this, but this sort of "personal language" is not generally used in the C world, especially if you expect anybody else to read your code in the future.
If you're doing this just for yourself, then feel free to #define whatever you want, but expect that once you start working with (or for) anybody else, you won't be able to continue using this sort of thing.
Using C macros unnecessarily can lead you into a world of pain, especially if you attempt to use it to expand code. There are uses for C macros, but this is not it.
Edit: I realize that my answer is tangential to your question, but I thought I should mention this since you say you are a C novice. Search for "C macro pitfalls" to get a full list of reasons why not to use macros. It's been previously discussed here.
In general, I strongly agree with the other respondents who tell you not to define your own macros purely for the sake of saving typing. The obfuscation is not worth it. Also, the particular macros you suggest are heinous. However, in Stroustrup's 1st Ed, he does something I rather like (sometimes):
#define Kase break; case
I became accustomed to the Python elif construct, so I often define the following:
#define elif(test) else if(test)
My purpose in doing this isn't to reduce typing, it's to keep indentation logical while maintaining consistent code width (I don't let my code go wider than 80 characters). I say this because to me this...
if(...) ...
else if(...) ...
else ...
...should be...
if(...)
{
...
}
else
if(...)
{
...
}
else
{
...
}
With my macro this becomes:
if(...)
{
...
}
elif(...)
{
...
}
else
{
...
}
It is always better to pass the loop variable to the macro.
A block - a macro has certain optimization problems. All compilers do not guarantee an optimized obj code for the "block scope" variables.
for example, the following code, when compiled with out any optimization options to gcc, prints two separate addresses for &i. And the same code when compiled with -O2 option will print the same address in both the blocks.
{
int i;
printf("address of i in first block is %u\n", &i);
}
{
int i;
printf("address of i in sec block is %u\n", &i);
}
Naming the language constructs appropriately makes the code more readable.
I like your idea, if you put it in the following way.
#define GREEN 1
#define YELLOW 2
#define RED 3
# define NUM_COLORS 3
#define COLOR_ITER (color,i) \
for(i=GREEN, color = colors[i]; \
i < NUM_COLORS; \
color = colors[++i])
int colors[3] = {GREEN, YELLOW, RED};
int
fun () {
int j;
color_t clr;
COLOR_ITER(clr, j) {
paint(clr);
}
}
Here, regardless of how it is written, the macro, COLOR_ITER, by its name, implies that you are looping for all available colors and doing "something" for each color. And this is a very easy-to-use macro.
And your quesion
Can I use the proprocessor to replace my sourcecode with my personal include to formatted source without the include ?
As everybody explained preprocessor will not help you in this case.
You can use your editor commands to automatically format your code, as you type it.

Resources