MantisBT - CMake
View Issue Details
0015730CMakeCMakepublic2015-09-08 08:512016-02-01 09:10
nmeunier 
 
normalminoralways
closedwon't fix 
Intel i7-3630QMwindows7 pro x64
CMake 3.0.2 
 
0015730: foreach() mis items from list when brackets are unclosed
I wanted to read all lines of a file, and iterate on them. But I wasn't same account of line in my ''foreach()'' as there was in my file. The last iterated line was like a concatenation of all remaining lines of the file. The cause is the incorrect item was containing an opening bracket '['.
<code cmake>
function(test_list_items _nb_lines _lines)
    set(_i 0)
    message("-- test '${_lines}'")
# string(REPLACE "]" "" _lines "${_lines}")
# string(REPLACE "[" "" _lines "${_lines}")
    foreach (_l IN LISTS _lines)
        math(EXPR _i "${_i}+1")
        message(" ${_i}: '${_l}'")
    endforeach()
    if (NOT _i EQUAL ${_nb_lines})
        message(" ${_i} != ${_nb_lines}")
    else()
        message(" OK")
    endif()
endfunction()

set(_a "line-1;line-2\;;line-3 // [;line-4")
test_list_items(4 "${_a}")

set(_a "line-1;line-2\;;line-3 // ];line-4")
test_list_items(4 "${_a}")

set(_a "line-1;line-2\; // [;line-3 // ];line-4")
test_list_items(4 "${_a}")

set(_a "line-1;line-2\; // ];line-3 // [;line-4")
test_list_items(4 "${_a}")

set(_a "line-1;line-2\; // {;line-3 // };line-4")
test_list_items(4 "${_a}")

set(_a "line-1;line-2\;;line-3 // {;line-4")
test_list_items(4 "${_a}")

set(_a "line-1;line-2\;;line-3 // };line-4")
test_list_items(4 "${_a}")
</code>

Here is the output:
<code>
-- test 'line-1;line-2\;;line-3 // [;line-4'
   1: 'line-1'
   2: 'line-2;'
   3: 'line-3 // [;line-4'
   3 != 4
-- test 'line-1;line-2\;;line-3 // ];line-4'
   1: 'line-1'
   2: 'line-2;'
   3: 'line-3 // ];line-4'
   3 != 4
-- test 'line-1;line-2\; // [;line-3 // ];line-4'
   1: 'line-1'
   2: 'line-2; // [;line-3 // ]'
   3: 'line-4'
   3 != 4
-- test 'line-1;line-2\; // ];line-3 // [;line-4'
   1: 'line-1'
   2: 'line-2; // ];line-3 // ['
   3: 'line-4'
   3 != 4
-- test 'line-1;line-2\; // {;line-3 // };line-4'
   1: 'line-1'
   2: 'line-2; // {'
   3: 'line-3 // }'
   4: 'line-4'
   OK
-- test 'line-1;line-2\;;line-3 // {;line-4'
   1: 'line-1'
   2: 'line-2;'
   3: 'line-3 // {'
   4: 'line-4'
   OK
-- test 'line-1;line-2\;;line-3 // };line-4'
   1: 'line-1'
   2: 'line-2;'
   3: 'line-3 // }'
   4: 'line-4'
   OK
</code>
The only workaround I found is to add these transformation before the ''foreach()'':
<code cmake>
    string(REPLACE "]" "" _lines "${_lines}")
    string(REPLACE "[" "" _lines "${_lines}")
</code>
No tags attached.
Issue History
2015-09-08 08:51nmeunierNew Issue
2015-09-09 09:47Brad KingNote Added: 0039377
2015-09-09 09:47Brad KingStatusnew => resolved
2015-09-09 09:47Brad KingResolutionopen => won't fix
2016-02-01 09:10Robert MaynardNote Added: 0040392
2016-02-01 09:10Robert MaynardStatusresolved => closed

Notes
(0039377)
Brad King   
2015-09-09 09:47   
This is documented behavior of ;-lists:

 http://www.cmake.org/cmake/help/v3.3/manual/cmake-language.7.html#lists [^]
 splitting on ; characters not following an unequal number of [ and ] characters

It is an unfortunate legacy behavior that is too established to change now.
(0040392)
Robert Maynard   
2016-02-01 09:10   
Closing resolved issues that have not been updated in more than 4 months.