# HG changeset patch # User Brice DAVIER # Date 1509373525 -3600 # Mon Oct 30 15:25:25 2017 +0100 # Node ID 5a79c4496748277500e618e1a1eb93958a6cfb5c # Parent e568074cf09d47c6a079e6392abcf8e5a9b3f3f9 read_namelist.m: character sequences may contain a / diff -r e568074cf09d -r 5a79c4496748 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 @@ -49,7 +49,6 @@ ## ## Notes Re: Use in Octave. ## -Line 83 causes a problem. Seems to work OK if commented out.FIXED -## -Cannot find end of namelist if marker (/) is preceded by space. ## -Copes with Fortran comment (!) e.g. ## &data1 ## a = 100.0 ! length metres @@ -99,8 +98,8 @@ line = []; ##TDuell 31/03/2013 Provisional fix L.102 PRN 1apr2013 endif nmlst_bdy = ""; - if (! isempty (line)); - idx = strfind (line, "/"); + if (! isempty (line)) + idx = find_ending_idx (line); else line = ""; endif @@ -109,7 +108,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 +120,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 +357,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);