44//! Rust.
55
66use super :: * ;
7+ use c2rust_ast_builder:: CaptureBy ;
78use failure:: format_err;
89use proc_macro2:: { TokenStream , TokenTree } ;
910
@@ -53,45 +54,97 @@ impl<'c> Translation<'c> {
5354 if n >= 2 {
5455 // `argv` and `argc`
5556
56- stmts. push ( mk ( ) . local_stmt ( Box :: new ( mk ( ) . local (
57- mk ( ) . mutbl ( ) . ident_pat ( "args" ) ,
58- Some ( mk ( ) . path_ty ( vec ! [ mk( ) . path_segment_with_args(
57+ stmts. push ( mk ( ) . local_stmt ( Box :: new ( {
58+ // ty = Vec<Vec<u8>>
59+ let ty = mk ( ) . path_ty ( vec ! [ mk( ) . path_segment_with_args(
5960 "Vec" ,
60- mk( ) . angle_bracketed_args( vec![
61- mk( ) . mutbl( ) . ptr_ty( mk( ) . abs_path_ty( vec![ "core" , "ffi" , "c_char" ] ) ) ,
62- ] ) ,
63- ) ] ) ) ,
64- Some ( mk ( ) . call_expr ( mk ( ) . path_expr ( vec ! [ "Vec" , "new" ] ) , vec ! [ ] ) ) ,
65- ) ) ) ) ;
66- stmts. push ( mk ( ) . semi_stmt ( mk ( ) . for_expr (
67- mk ( ) . ident_pat ( "arg" ) ,
68- mk ( ) . call_expr ( args_fn, vec ! [ ] ) ,
69- mk ( ) . block ( vec ! [ mk( ) . semi_stmt( mk( ) . method_call_expr(
70- mk( ) . path_expr( vec![ "args" ] ) ,
71- "push" ,
72- vec![ mk( ) . method_call_expr(
73- mk( ) . method_call_expr(
74- mk( ) . call_expr(
75- // TODO(kkysen) change `"std"` to `"alloc"` after `#![feature(alloc_c_string)]` is stabilized in `1.63.0`
76- mk( ) . abs_path_expr( vec![ "std" , "ffi" , "CString" , "new" ] ) ,
77- vec![ mk( ) . path_expr( vec![ "arg" ] ) ] ,
78- ) ,
79- "expect" ,
80- vec![ mk( ) . lit_expr( "Failed to convert argument into CString." ) ] ,
81- ) ,
82- "into_raw" ,
61+ mk( ) . angle_bracketed_args( vec![ mk( ) . path_ty( vec![ mk( )
62+ . path_segment_with_args(
63+ "Vec" ,
64+ mk( ) . angle_bracketed_args( vec![ mk( ) . ident_ty( "u8" ) ] ) ,
65+ ) ] ) ] ) ,
66+ ) ] ) ;
67+ // map_arg = |arg| {
68+ // (::std::ffi::CString::new(arg))
69+ // .expect("Failed to convert argument into CString.")
70+ // .into_bytes_with_nul()
71+ // }
72+ let cstring_call = mk ( ) . call_expr (
73+ // TODO(kkysen) change `"std"` to `"alloc"` after `#![feature(alloc_c_string)]` is stabilized in `1.63.0`
74+ mk ( ) . abs_path_expr ( vec ! [ "std" , "ffi" , "CString" , "new" ] ) ,
75+ vec ! [ mk( ) . path_expr( vec![ "arg" ] ) ] ,
76+ ) ;
77+ let expect_arg = mk ( ) . lit_expr ( "Failed to convert argument into CString." ) ;
78+ let map_arg = mk ( ) . closure_expr (
79+ CaptureBy :: Ref ,
80+ Movability :: Movable ,
81+ vec ! [ mk( ) . ident_pat( "arg" ) ] ,
82+ ReturnType :: Default ,
83+ mk ( ) . method_chain_expr (
84+ cstring_call,
85+ vec ! [
86+ ( mk( ) . path_segment( "expect" ) , vec![ expect_arg] ) ,
87+ ( mk( ) . path_segment( "into_bytes_with_nul" ) , vec![ ] ) ,
88+ ] ,
89+ ) ,
90+ ) ;
91+ // init = args_fn
92+ // .map(map_arg)
93+ // .collect();
94+ let init = mk ( ) . method_chain_expr (
95+ mk ( ) . call_expr ( args_fn, vec ! [ ] ) ,
96+ vec ! [
97+ ( mk( ) . path_segment( "map" ) , vec![ map_arg] ) ,
98+ ( mk( ) . path_segment( "collect" ) , vec![ ] ) ,
99+ ] ,
100+ ) ;
101+ mk ( ) . local ( mk ( ) . mutbl ( ) . ident_pat ( "args_strings" ) , Some ( ty) , Some ( init) )
102+ } ) ) ) ;
103+
104+ stmts. push ( mk ( ) . local_stmt ( Box :: new ( {
105+ // ty = Vec<*mut ::core::ffi::c_char>
106+ let ty = mk ( ) . path_ty ( vec ! [ mk( ) . path_segment_with_args(
107+ "Vec" ,
108+ mk( ) . angle_bracketed_args( vec![ mk( )
109+ . mutbl( )
110+ . ptr_ty( mk( ) . abs_path_ty( vec![ "core" , "ffi" , "c_char" ] ) ) ] ) ,
111+ ) ] ) ;
112+ // map_arg = |arg| arg.as_mut_ptr() as *mut ::core::ffi::c_char
113+ let map_arg = mk ( ) . closure_expr (
114+ CaptureBy :: Ref ,
115+ Movability :: Movable ,
116+ vec ! [ mk( ) . ident_pat( "arg" ) ] ,
117+ ReturnType :: Default ,
118+ mk ( ) . cast_expr (
119+ mk ( ) . method_call_expr ( mk ( ) . ident_expr ( "arg" ) , "as_mut_ptr" , vec ! [ ] ) ,
120+ mk ( ) . mutbl ( )
121+ . ptr_ty ( mk ( ) . abs_path_ty ( vec ! [ "core" , "ffi" , "c_char" ] ) ) ,
122+ ) ,
123+ ) ;
124+ // chain_arg = ::core::iter::once(::core::ptr::null_mut())
125+ let chain_arg = mk ( ) . call_expr (
126+ mk ( ) . abs_path_expr ( vec ! [ "core" , "iter" , "once" ] ) ,
127+ vec ! [ mk( ) . call_expr(
128+ mk( ) . abs_path_expr( vec![ "core" , "ptr" , "null_mut" ] ) ,
83129 vec![ ] ,
84130 ) ] ,
85- ) ) ] ) ,
86- None :: < Ident > ,
87- ) ) ) ;
88- stmts. push ( mk ( ) . semi_stmt ( mk ( ) . method_call_expr (
89- mk ( ) . path_expr ( vec ! [ "args" ] ) ,
90- "push" ,
91- vec ! [
92- mk( ) . call_expr( mk( ) . abs_path_expr( vec![ "core" , "ptr" , "null_mut" ] ) , vec![ ] ) ,
93- ] ,
94- ) ) ) ;
131+ ) ;
132+ // init = args_strings
133+ // .iter_mut()
134+ // .map(map_arg)
135+ // .chain(chain_arg)
136+ // .collect()
137+ let init = mk ( ) . method_chain_expr (
138+ mk ( ) . ident_expr ( "args_strings" ) ,
139+ vec ! [
140+ ( mk( ) . path_segment( "iter_mut" ) , vec![ ] ) ,
141+ ( mk( ) . path_segment( "map" ) , vec![ map_arg] ) ,
142+ ( mk( ) . path_segment( "chain" ) , vec![ chain_arg] ) ,
143+ ( mk( ) . path_segment( "collect" ) , vec![ ] ) ,
144+ ] ,
145+ ) ;
146+ mk ( ) . local ( mk ( ) . mutbl ( ) . ident_pat ( "args_ptrs" ) , Some ( ty) , Some ( init) )
147+ } ) ) ) ;
95148
96149 let argc_ty: Box < Type > = match self . ast_context . index ( parameters[ 0 ] ) . kind {
97150 CDeclKind :: Variable { ref typ, .. } => self . convert_type ( typ. ctype ) ,
@@ -105,8 +158,7 @@ impl<'c> Translation<'c> {
105158 "Cannot find type of 'argv' argument in main function" ,
106159 ) ) ,
107160 } ?;
108-
109- let args = mk ( ) . ident_expr ( "args" ) ;
161+ let args = mk ( ) . ident_expr ( "args_ptrs" ) ;
110162 let argc = mk ( ) . binary_expr (
111163 BinOp :: Sub ( Default :: default ( ) ) ,
112164 mk ( ) . method_call_expr ( args. clone ( ) , "len" , no_args. clone ( ) ) ,
0 commit comments