Solved

Converting a function-like macro to a function

Posted on 2009-07-06
4
171 Views
Last Modified: 2012-05-07
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

0
Comment
Question by:letharion
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
4 Comments
 
LVL 53

Expert Comment

by:Infinity08
ID: 24783443
>> 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
 
LVL 53

Accepted Solution

by:
Infinity08 earned 250 total points
ID: 24783470
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
 
LVL 6

Author Comment

by:letharion
ID: 24783658
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
 
LVL 53

Expert Comment

by:Infinity08
ID: 24783736
>> 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

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Read file descriptor 3 in C 14 127
C hashtable library 3 113
distributed computing in Python 4 155
Windows Server 2012  Backup - HyperV host 18 113
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question