# HG changeset patch # User Brice DAVIER # Date 1509373525 -3600 # Mon Oct 30 15:25:25 2017 +0100 # Node ID bb7e74f6fa1b607c50cad1306ad1113d562002a8 # Parent e568074cf09d47c6a079e6392abcf8e5a9b3f3f9 read_namelist.m: character sequences may contain a / diff -r e568074cf09d -r bb7e74f6fa1b inst/read_namelist.m --- a/inst/read_namelist.m Sat Oct 21 12:57:04 2017 +0200 +++ b/inst/read_namelist.m Mon Oct 30 15:25:25 2017 +0100 @@ -100,7 +100,7 @@ endif nmlst_bdy = ""; if (! isempty (line)); - idx = strfind (line, "/"); + idx = find_ending_idx(line); else line = ""; endif @@ -109,7 +109,7 @@ nmlst_bdy = [ nmlst_bdy " " line ]; ++ii; line = lines{ii}; - idx = strfind (line, "/"); + idx = find_ending_idx(line); endwhile if (! isempty (idx) && idx(1) > 1) nmlst_bdy = [ nmlst_bdy " " line(1:idx(1)-1) ]; @@ -121,6 +121,48 @@ endfunction +## Internal function to find the position of the slash terminating the namelist +function idx = find_ending_idx(strng) + + % Find all / + idx_all = strfind (strng, "/"); + idx = []; + % Only keep the ones not quoted + for ii = 1:size(idx_all, 2) + if ( !is_quoted(strng, idx_all(ii), '"') && !is_quoted(strng, idx_all(ii), '''') ) + idx = [idx idx_all(ii)]; + endif + endfor +endfunction + +## Internal function to check if a character at a position idx in a string strng is quoted by the character quote +function l = is_quoted(strng, idx, quote) + + % Find location of all quotes + idx_quotes = strfind(strng, quote); + if (isempty(idx_quotes)) + % There are no quotes + l = false; + return + endif + ii = 1; + while (ii <= size(idx_quotes, 2)) + % Find the first quote after the character + if (idx_quotes(ii) > idx) + % If we counted an even number of quote, this character is quoted + if (mod(ii, 2) == 0) + l = true; + return + else + l = false; + return + endif + endif + ++ii; + endwhile + % The character is behind all quotes + l = false; +endfunction ## Internal function to parse the body text of a namelist section. ## Limitations: the following patterns are prohibited inside the literal @@ -316,3 +358,21 @@ %! nm = read_namelist (fn); %! unlink (fn); %! assert (nm.test.a, 1, eps); + +## Check if character sequences can contain the / character +%!test +%! fn = tempname(); +%! fid = fopen (fn, "w"); +%! fprintf (fid, "&test\n"); +%! fprintf (fid, " a = '/',\n"); % inside apostrophes +%! fprintf (fid, " b = ""/"",\n"); % inside double quotes +%! fprintf (fid, " c = '""/',\n"); % with double quotes inside apostrophes +%! fprintf (fid, " d = ""'/"",\n"); % with apostrophes inside double quotes +%! fprintf (fid, "/\n"); +%! fclose (fid); +%! nm = read_namelist (fn); +%! unlink (fn); +%! assert (strcmp(nm.test.a, '/'), 1, eps); +%! assert (strcmp(nm.test.b, '/'), 1, eps); +%! assert (strcmp(nm.test.c, '"/'), 1, eps); +%! assert (strcmp(nm.test.d, '''/'), 1, eps);