vstakhov / libucl

Universal configuration library parser
BSD 2-Clause "Simplified" License
1.62k stars 138 forks source link

Workaround for issue processing include paths with '\' on Windows #209

Open MeachamusPrime opened 5 years ago

MeachamusPrime commented 5 years ago

I'm successfully building with clang-cl in Visual Studio compatibility mode on Windows using CMake for Windows and Google Ninja. My goal was to get around using any paywalled Microsoft software. Downloading the Windows 10 SDK was required for success. The build works with one quirk.

When the include paths on windows are passed manually (I didn't test any automated functionality), as in:

.try_include(path=["D:\Users\Me\source\project\things\thingClass","D:\Users\Me\source\project\things\include"]) "standardtypes.inc"

the '\' characters have been removed when processing the directories.

The workaround I propose to be added to the README is a warning that users on Windows should change all path related '\' characters for include paths to '/' characters.


Details: Apologies if this has been remedied already. My testing is on an older version as the latest version breaks some of my macros. It's not convenient for me to work a patch for the latest version at the moment or I would have simply made a pull request.

The reason appears to be that while iterating through the array, I think it is going through ucl_object_tostring(), but it eventually gets to ucl_copy_value_trash() and obj->type is not set to UCL_STRING so it goes down to call ucl_object_emit_single_json() and the JSON emitter is removing the '\' characters, believing them to be escape characters.

        if (obj->type == UCL_STRING) {

            /* Special case for strings */
            if (obj->flags & UCL_OBJECT_BINARY) {
                deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len);
                if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
                    memcpy (deconst->trash_stack[UCL_TRASH_VALUE],
                            obj->value.sv,
                            obj->len);
                    deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
                }
            }
            else {
                deconst->trash_stack[UCL_TRASH_VALUE] = malloc (obj->len + 1);
                if (deconst->trash_stack[UCL_TRASH_VALUE] != NULL) {
                    memcpy (deconst->trash_stack[UCL_TRASH_VALUE],
                            obj->value.sv,
                            obj->len);
                    deconst->trash_stack[UCL_TRASH_VALUE][obj->len] = '\0';
                    deconst->value.sv = obj->trash_stack[UCL_TRASH_VALUE];
                }
            }
        }
        else {
            /* Just emit value in json notation */
            deconst->trash_stack[UCL_TRASH_VALUE] = ucl_object_emit_single_json (obj);
            deconst->len = strlen (obj->trash_stack[UCL_TRASH_VALUE]);
        }
davidchisnall commented 3 years ago

Is the problem here not simply that normal escaping is applied, so '\Me' is treated as the escape character '\M' followed by 'e'? Does it work if you properly escape the backslashes as '\'? Single-quoted strings are not escaped, so does using single-quotes for Windows paths work?