• C

Converting a function-like macro to a function

I'm using the Flex/Bison combination and is adjusting it to my needs.
I'm nearly done, but something gets wrong with my input-data, and I'm trying to trace the error.

Here I hit a roadblock, because the data is read by a function-like macro, and gdb seems to be unable to step into a macro.

How do I replace the macro with "real" code, so that it becomes easier to debug it?
Alternatively, can I make gdb step in this code?

The macro isn't huge, so I'm gonna try to work it out regardless, but I find the question interesting :)
// Original macro
#ifndef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
   if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
      { \
      int c = '*'; \
      int n; \
      for ( n = 0; n < max_size && \
              (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
         buf[n] = (char) c; \
      if ( c == '\n' ) \
         buf[n++] = (char) c; \
      if ( c == EOF && ferror( yyin ) ) \
         YY_FATAL_ERROR( "input in flex scanner failed" ); \
      result = n; \
      } \
   else \
      { \
      errno=0; \
      while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
         { \
         if( errno != EINTR) \
            { \
            YY_FATAL_ERROR( "input in flex scanner failed" ); \
            break; \
            } \
         errno=0; \
         clearerr(yyin); \
         } \
      }\
\
 
#endif
 
//My replacement below
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) { \
   if(done == 1) (yy_n_chars) = YY_NULL;\
   else {\
      std::ostringstream str;\
      int j = 0;\
      do {\
         str << progs[progPointer] << " ";\
      } while (progs[progPointer++] != 99.0f && str.str().size() < num_to_read);\
\
      for(;j < str.str().size(); j++)\
         (&(yy_buffer_stack)[(yy_buffer_stack_top)]->yy_ch_buf[number_to_move])[j] = str.str().c_str()[j];\
\
      (yy_n_chars) = j;\
      if(progs[i] == 99.0f)\
      done = 1;\
   }\
}\
 
//Calling code
      YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
         (yy_n_chars), (size_t) num_to_read );

Open in new window

LVL 6
letharionAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Infinity08Commented:
>> Here I hit a roadblock, because the data is read by a function-like macro, and gdb seems to be unable to step into a macro.

A macro is not a function - whenever you "call" a macro, it is replaced inline with the code for the macro, so there's no function call that gdb can step into.


>> How do I replace the macro with "real" code, so that it becomes easier to debug it?

Make it a function call :
void fun(/* the arguments ... */) {
  // whatever you want to do ...
}
 
#define MACRO(/* the arguments ... */) fun(/* the arguments ... */)

Open in new window

0
Infinity08Commented:
So, for your example, you'd get something like (verify that it's correct, because your macro code was very strange, as it didn't use the arguments ...) :
void my_yy_input(int *buf, int &yy_n_chars, size_t num_to_read) {
  if (done == 1) {
    yy_n_chars = YY_NULL;
  }
  else {
    std::ostringstream str;
    int j = 0;
    do {
      str << progs[progPointer] << " ";
    } while (progs[progPointer++] != 99.0f && str.str().size() < num_to_read);
 
    for (; j < str.str().size(); j++) {
      buf[j] = str.str().c_str()[j];
    }
 
    yy_n_chars = j;
    if (progs[i] == 99.0f) {
      done = 1;
    }
  }
}
 
#define YY_INPUT(buf, result, max_size) my_yy_input(buf, result, max_size)

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
letharionAuthor Commented:
Thank you, works well :)

>your macro code was very strange, as it didn't use the arguments
Thanks for pointing that out. After experimenting with directly replacing the macro with code and going back, I had accidentally left the names of the variables like they are before in the scope outside of the function.

>A macro is not a function - whenever you "call" a macro, it is replaced inline with the code for the macro, so there's no function call that gdb can step into.
I thought this was done by the PP before compilation, and thus gdb could (in theory) have done the same. But maybe I've missunderstood the process, or gdb just has not implemented that function. (Maybe it'd be harder than I imagine)
In both mine, and therefore your code, progs[i] is used, and now that I have a function I get the expected complaint that i is undefined. This "just worked" in the macro, which wasn't to my advantage.
0
Infinity08Commented:
>> I thought this was done by the PP before compilation

Exactly. The pre-processor modifies the source code before passing it to the compiler. So, the compiler is never aware that there even was a macro to begin with. The generated code that gdb works with has no function call as a result.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.