0

I have the below program. It passes a macro as optional arg to variadic function. Within that function definition, shall we able to get that macro without expansion. I have used type as 'char *' and is showing the macro expanded string. Any ways to get macro as it is.

#include <stdio.h>
#include <stdarg.h>

#define CONN_DISALLOW 3201008
#define SYSLOG_CONN_DISALLOW  \
    "%d: Disallowing new connections. Reason: %s.\n", CONN_DISALLOW

void cp_syslog(int syslogid, ...);

void cp_syslog(int syslogid, ...)
{
        char *syslog_disallow;
        va_list ap;
        va_start(ap, syslogid);

        syslog_disallow = va_arg(ap, char *);

        printf("String is %s", syslog_disallow);
        printf("Macro is %s", SYSLOG_CONN_DISALLOW);

        va_end(ap);
}

int main()
{
        int id = 2;
        cp_syslog(id, SYSLOG_CONN_DISALLOW);
        return 0;
}

Now got the output as:

String is %d: Disallowing new connections. Reason: %s.
Macro is %d: Disallowing new connections. Reason: %s.

Expecting as:

String is SYSLOG_CONN_DISALLOW

My expectation here is how to process a particular macro if different macros are passed as optional argument to the same variadic func.

like below:

cp_syslog(id, SYSLOG_CONN_DISALLOW);
cp_syslog(id, SYSLOG_CONN_ALLOW);
cp_syslog(id, SYSLOG_ICMP_DISALLOW);
  • 1
    Hm. Macros get expanded, that's what they are for. After preprocessing, the macro names disappear from the source code. You can pass the name of the macro as `"SYSLOG_CONN_DISALLOW"` to get what you want, but it doesn't look like what you _really_ want. Apparently you are trying to have a system of error codes and related messages. – M Oehm Apr 22 '20 at 16:24
  • @M Oehm and @bruno : I got your point of using `"SYSLOG_CONN_DISALLOW"`. But I was not allowed to send MACRO as above. Because there are nearly 400-500 different macros are passed as arg to `cp_syslog()`. With this programming, any possibilities are there to extract macro name. – renga_in_stack Apr 22 '20 at 16:42
  • Is the function `cp_syslog` always called as inyour examples: `syslog(id, macro)`? If so, you don't need variadic arguments, but you could wrap `cp_syslog` in a stringizing macro. – M Oehm Apr 22 '20 at 16:46
  • @renga_in_stack I edited my answer – bruno Apr 22 '20 at 17:03
  • @bruno: I am perfectly OK with using intermediate macro of `NAME_VALUE`. But I should not touch the caller `cp_syslog()`. As i mentioned in above comment, there are multiple callers for cp_syslog with different macros. I have to change in each and every caller like below. I was not able to think beyond an extent. `cp_syslog(id, NAME_VALUE(SYSLOG_CONN_DISALLOW)); cp_syslog(id,NAME_VALUE( SYSLOG_CONN_ALLOW)); cp_syslog(id, NAME_VALUE(SYSLOG_ICMP_DISALLOW));` – renga_in_stack Apr 22 '20 at 17:33
  • @renga_in_stack yes you have to change them, there is no magic, *but* you can automatize these changes using `sed` or other tool doing changes with regular expression. I just recommend you to do a backup of the sources before to do these automatic editions :-) – bruno Apr 22 '20 at 17:35
  • 1
    @bruno : Thanks for helping out and confirming few things in macros. – renga_in_stack Apr 22 '20 at 17:42

1 Answers1

1

A first possibility is to just do

cp_syslog(id, "SYSLOG_CONN_DISALLOW");

Execution :

pi@raspberrypi:/tmp $ ./a.out
String is SYSLOG_CONN_DISALLOWMacro is %d: Disallowing new connections. Reason: %s.
pi@raspberrypi:/tmp $ 

(a newline is missed in the first printf or do cp_syslog(id, "SYSLOG_CONN_DISALLOW\n"))

But this is artificial and even the definition of cp_syslog is artificial because that one knows the macro is SYSLOG_CONN_DISALLOW being in its definition.


If you want to give to 'something else' both the name of a macro and its 'value' just use an intermediate macro like :

#define NAME_VALUE(x) #x, x

The expansion of NAME_VALUE(SYSLOG_CONN_DISALLOW) is "SYSLOG_CONN_DISALLOW", "%d: Disallowing new connections. Reason: %s.\n", 3201008

That time cp_syslog does not have to know it applies on SYSLOG_CONN_DISALLOW :

#include <stdio.h>
#include <stdarg.h>

#define CONN_DISALLOW 3201008
#define SYSLOG_CONN_DISALLOW  \
    "%d: Disallowing new connections. Reason: %s.\n", CONN_DISALLOW

#define NAME_VALUE(x) #x, x /* ADDED */

void cp_syslog(int syslogid, ...);

void cp_syslog(int syslogid, ...)
{
  char *syslog_disallow;
  va_list ap;
  va_start(ap, syslogid);

  syslog_disallow = va_arg(ap, char *);

  printf("String is %s\n", syslog_disallow); /* \n ADDED */
  printf("Macro is %s", va_arg(ap, char *)); /* MODIFIED */

  va_end(ap);
}

int main()
{
        int id = 2;
        cp_syslog(id, NAME_VALUE(SYSLOG_CONN_DISALLOW)); /* MODIFIED */
        return 0;
}

Compilation and executon :

pi@raspberrypi:/tmp $ gcc pp.c
pi@raspberrypi:/tmp $ ./a.out
String is SYSLOG_CONN_DISALLOW
Macro is %d: Disallowing new connections. Reason: %s.
pi@raspberrypi:/tmp $ 
bruno
  • 32,421
  • 7
  • 25
  • 37