Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create string literal from -D compiler defined variable of a Windows path

Under Windows, I have an environment variable that contains a Windows-style path. I'd like to build that path into my program and print it out. So if my path is c:\top, I pass it into the compiler using -DTOP=$(TOP). Note I cannot convert it to c:\\top before I pass it into the compiler.

Right now, I have the equivalent of:

#define TOP=c:\top

I want the equivalent of:

char path[]="c:\\top";

I can't just use the stringafication operator:

#define WRAP1(X) #X
#define WRAP(X) WRAP1(X)
char path[] = WRAP(TOP);

That just results in the string "c:\top" which the compiler views as an escape sequence (i.e. \t).

I think a possible solution would be to construct a string literal, but other solutions will be also be fine. Is there a way to use macros to construct a string literal that would yield:

char path[] = R"foo(c:\top)foo";

So far, all my attempts have failed for reasons involving the variations of the " or ( ) or the \ .

Thanks.

like image 782
shol74 Avatar asked Jul 02 '15 20:07

shol74


1 Answers

You can convert your defined path to a string by prefixing it with the stringizing operator #. However, this only works in macros. You actually need a double-macro to make it work properly, otherwise it just prints TOP. Also placing the pathname in quotes is important - oh the example has the path stored under the env PathDirName

Defining the path for the compiler -

/DTOP="\"$(PathDirName)\\""

Using within the code

#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)

char path[] = STRINGIZE(TOP);

This has worked for me. You nearly had it working, so hope this helps.

[EDIT] I can see the problem now - within C:\top - its taking the 'backslash t' as a control code - '\t'. This appoarch is becoming a little bit of a nightmare to work out - as you really need to create the file name with two slashes or use forward slashes. I do feel I have confused issues here by answering before reviewing fully what has happened. I have tried several methods - but not being able to change the passed in define - I can only suggest using a regex library or manual scanning the string - replacing the control charactors with the correct '\' letter.

I've knocked up an example showing this just with the '\t' in your example - It's not nice code, it's written to explain what is being done, hopefully it gives an visual example and it does (in a not so nice way) sort out the ONE issue you are having with 'C:\top' .. as I have said - if using this cough, method, you will need to handle all control codes. :-)

char stringName[256];
char* pRefStr = STRING(TOP);
char* pDestStr = stringName;
int nStrLen = strlen( pRefStr );

for( int nIndex = 0; nIndex < nStrLen; nIndex++ )
{
    if ( *pRefStr == '\t' )
    {
        *pDestStr++ = '\\';
        *pDestStr++ = 't';
        pRefStr++;
    }
    else
    {
        *pDestStr++ = *pRefStr++;
    }
}
*pDestStr = '\0';

Once again - sorry for any confusion - I've left my answer here as reference for you - and hopefully someone will come up with a way of handling the define-string (with the control charactors).

thanks, Neil

like image 94
Neil Avatar answered Sep 22 '22 02:09

Neil