3

In VS2010, I wrote the following variadic macros to dump out information to files.

#define INDENT(fp, indent) for(size_t __i = 0; __i < (indent); ++__i) fprintf((fp), "  ")
// IND_FP = indented fprintf.
// This macro uses two IMPLICIT parameters.
// 1. (FILE *)fp is a pointer to the output file.
// 2. (size_t)indent specifies the indentation level.
#define IND_FP(format, ...) do{ INDENT(fp, indent); fprintf(fp, format, __VA_ARGS__); }while(0)

These macros frequently occur in my program.

void CMAP::dump_info(FILE *fp, size_t indent){
  IND_FP("<cmap tableVersion=\"0x%08x\" numberOfEncodingTables=\"%d\">\n",
    table_version_number, num_encoding_tables);
  //...
  IND_FP("</cmap>\n");
}

Sadly, now I have to migrate my code to the antediluvian IDE, VC++6.0, which does NOT support variadic macro. I wrote a variadic function instead.

void IND_FP(FILE *fp, size_t indent, char *format, ...){
  INDENT(fp, indent);
  va_list arg_ptr;
  va_start(arg_ptr, format);
  vfprintf(fp, format, arg_ptr);
  va_end(arg_ptr);
}

But I have to change the tens if not hundreds lines of code from IND_FP(format, ...) to IND_FP(fp, indent, format, ...).

Is there any trick of macro that can help me out? Or I'd better use explicit arguments and get used to redundancy?

a3f
  • 8,517
  • 1
  • 41
  • 46
lzl124631x
  • 4,485
  • 2
  • 30
  • 49
  • 1
    Oh boy, you are definitely migrating in the wrong direction. What, specifically, is the reason you need to use VC++ 6? Maybe it can be worked around while still using a modern compiler? – Cody Gray - on strike May 25 '14 at 08:56
  • @CodyGray. My professor enjoys VC++6.0. He though it's lightweight and tiny, while VS2010 seems too bulky. So I have to migrate my code when submit. I'll try to persuade him, but a person at his age is prone to be stubborn. – lzl124631x May 25 '14 at 09:20
  • 1
    Running `cl.exe` from the command line is even more lightweight and tiny. He shouldn't need to open your code in an IDE at all! Seriously, your argument shouldn't be that you like using any particular development environment better. Like most C++ devs, I too loved the VC++6 environment. The problem, and the argument you need to make, is that the compiler it's bundled with is literally too old to teach you useful, modern C++ practices. – Cody Gray - on strike May 25 '14 at 09:22
  • @CodyGray. Thanks. This argument is more persuasive and I'd like to share it with my professor. Anyway, I am still curious about whether it is possible to work around this problem in VC++6. – lzl124631x May 25 '14 at 09:36

3 Answers3

1
#define IND_FP Logger(indent)

class Logger {
  public:
    Logger(int indent);
    int operator()(FILE* fp, char* format, ...);
  private:
    // an exercise for the reader
};
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • 1
    Having said that, I would not recommend this in serious development, just as I would not recommend any macros at all. Or your printf-based logging style. Or VC6. Or, by the looks of it, your professor. – n. m. could be an AI May 25 '14 at 09:54
0

You could get round variadics by not using them. Use ofstream instead of FILE*. Something like this

#define LOGGER(logfile,loginfo)  logfile << loginfo << std::endl

Say you've declared an ofstream called logfile. For simple things, you can use

LOGGER(logfile, x);

If you wish to get more complex, you could use

LOGGER(logfile, "x = " << x << "  b=" << b);

For the indent, you could use a global

// declaration
char spaces[128];
...
// Initialization
memset(spaces, ' ', sizeof(spaces));

#define LOGGER(logfile,indent,loginfo) \
    spaces[indent] = '\0'; \
    logfile << spaces << loginfo << std::endl; \
    spaces[indent] = ' '

So in the same way, if you wish to indent by 3

LOGGER(logfile, 3, "x=" << x << "   y=" << y << "   z=" << z);

C++ << is not as elegant as printf for formatting but it will get you round the problem of using variadics.

cup
  • 7,589
  • 4
  • 19
  • 42
0
FILE *g_fp;
size_t g_indent;

void ind_fp(char *format, ...){
  INDENT(g_fp, g_indent);
  va_list arg_ptr;
  va_start(arg_ptr, format);
  vfprintf(g_fp, format, arg_ptr);
  va_end(arg_ptr);
}

#define IND_FP (g_fp = fp, g_indent = indent, &ind_fp)

This might work for your situation.

Zhang Boyang
  • 81
  • 1
  • 2