@@ -16,13 +16,15 @@ use nom::{
1616    IResult , 
1717} ; 
1818use  std:: { 
19+     char, 
1920    collections:: { HashMap ,  HashSet } , 
2021    error:: Error , 
2122    fmt:: { Debug ,  Display } , 
2223    io:: { BufRead ,  Write } , 
2324    ops:: Not , 
2425} ; 
2526use  uucore:: error:: UError ; 
27+ use  uucore:: show_warning; 
2628
2729#[ derive( Debug ,  Clone ) ]  
2830pub  enum  BadSequence  { 
@@ -293,7 +295,9 @@ impl Sequence {
293295            Self :: parse_class, 
294296            Self :: parse_char_equal, 
295297            // NOTE: This must be the last one 
296-             map ( Self :: parse_backslash_or_char,  |s| Ok ( Self :: Char ( s) ) ) , 
298+             map ( Self :: parse_backslash_or_char_with_warning,  |s| { 
299+                 Ok ( Self :: Char ( s) ) 
300+             } ) , 
297301        ) ) ) ( input) 
298302        . map ( |( _,  r) | r) 
299303        . unwrap ( ) 
@@ -302,10 +306,16 @@ impl Sequence {
302306    } 
303307
304308    fn  parse_octal ( input :  & [ u8 ] )  -> IResult < & [ u8 ] ,  u8 >  { 
309+         // For `parse_char_range`, `parse_char_star`, `parse_char_repeat`, `parse_char_equal`. 
310+         // Because in these patterns, there's no ambiguous cases. 
311+         preceded ( tag ( "\\ " ) ,  Self :: parse_octal_up_to_three_digits) ( input) 
312+     } 
313+ 
314+     fn  parse_octal_with_warning ( input :  & [ u8 ] )  -> IResult < & [ u8 ] ,  u8 >  { 
305315        preceded ( 
306316            tag ( "\\ " ) , 
307317            alt ( ( 
308-                 Self :: parse_octal_up_to_three_digits , 
318+                 Self :: parse_octal_up_to_three_digits_with_warning , 
309319                // Fallback for if the three digit octal escape is greater than \377 (0xFF), and therefore can't be 
310320                // parsed as as a byte 
311321                // See test `test_multibyte_octal_sequence` 
@@ -319,16 +329,29 @@ impl Sequence {
319329            recognize ( many_m_n ( 1 ,  3 ,  one_of ( "01234567" ) ) ) , 
320330            |out :  & [ u8 ] | { 
321331                let  str_to_parse = std:: str:: from_utf8 ( out) . unwrap ( ) ; 
332+                 u8:: from_str_radix ( str_to_parse,  8 ) . ok ( ) 
333+             } , 
334+         ) ( input) 
335+     } 
322336
323-                 match  u8:: from_str_radix ( str_to_parse,  8 )  { 
324-                     Ok ( ue)  => Some ( ue) , 
325-                     Err ( _pa)  => { 
326-                         // TODO 
327-                         // A warning needs to be printed here 
328-                         // See https://github.com/uutils/coreutils/issues/6821 
329-                         None 
330-                     } 
337+     fn  parse_octal_up_to_three_digits_with_warning ( input :  & [ u8 ] )  -> IResult < & [ u8 ] ,  u8 >  { 
338+         map_opt ( 
339+             recognize ( many_m_n ( 1 ,  3 ,  one_of ( "01234567" ) ) ) , 
340+             |out :  & [ u8 ] | { 
341+                 let  str_to_parse = std:: str:: from_utf8 ( out) . unwrap ( ) ; 
342+                 let  result = u8:: from_str_radix ( str_to_parse,  8 ) . ok ( ) ; 
343+                 if  result. is_none ( )  { 
344+                     let  origin_octal:  & str  = std:: str:: from_utf8 ( input) . unwrap ( ) ; 
345+                     let  actual_octal_tail:  & str  = std:: str:: from_utf8 ( & input[ 0 ..2 ] ) . unwrap ( ) ; 
346+                     let  outstand_char:  char  = char:: from_u32 ( input[ 2 ]  as  u32 ) . unwrap ( ) ; 
347+                     show_warning ! ( 
348+                         "the ambiguous octal escape \\ {} is being\n         interpreted as the 2-byte sequence \\ 0{}, {}" , 
349+                         origin_octal, 
350+                         actual_octal_tail, 
351+                         outstand_char
352+                     ) ; 
331353                } 
354+                 result
332355            } , 
333356        ) ( input) 
334357    } 
@@ -360,6 +383,14 @@ impl Sequence {
360383        alt ( ( Self :: parse_octal,  Self :: parse_backslash,  Self :: single_char) ) ( input) 
361384    } 
362385
386+     fn  parse_backslash_or_char_with_warning ( input :  & [ u8 ] )  -> IResult < & [ u8 ] ,  u8 >  { 
387+         alt ( ( 
388+             Self :: parse_octal_with_warning, 
389+             Self :: parse_backslash, 
390+             Self :: single_char, 
391+         ) ) ( input) 
392+     } 
393+ 
363394    fn  single_char ( input :  & [ u8 ] )  -> IResult < & [ u8 ] ,  u8 >  { 
364395        take ( 1usize ) ( input) . map ( |( l,  a) | ( l,  a[ 0 ] ) ) 
365396    } 
0 commit comments