44//! Rust.
55
66use super :: * ;
7+ use c2rust_ast_builder:: CaptureBy ;
78use failure:: format_err;
89use proc_macro2:: { TokenStream , TokenTree } ;
910
@@ -53,45 +54,96 @@ 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+ // 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+ // |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+ mk ( ) . abs_path_expr ( vec ! [ "std" , "ffi" , "CString" , "new" ] ) ,
74+ vec ! [ mk( ) . path_expr( vec![ "arg" ] ) ] ,
75+ ) ;
76+ let expect_arg = mk ( ) . lit_expr ( "Failed to convert argument into CString." ) ;
77+ let map_arg = mk ( ) . closure_expr (
78+ CaptureBy :: Ref ,
79+ Movability :: Movable ,
80+ vec ! [ mk( ) . ident_pat( "arg" ) ] ,
81+ ReturnType :: Default ,
82+ mk ( ) . method_chain_expr (
83+ cstring_call,
84+ vec ! [
85+ ( mk( ) . path_segment( "expect" ) , vec![ expect_arg] ) ,
86+ ( mk( ) . path_segment( "into_bytes_with_nul" ) , vec![ ] ) ,
87+ ] ,
88+ ) ,
89+ ) ;
90+ // (args_fn)
91+ // .map(map_arg)
92+ // .collect();
93+ let init = mk ( ) . method_chain_expr (
94+ mk ( ) . call_expr ( args_fn, vec ! [ ] ) ,
95+ vec ! [
96+ ( mk( ) . path_segment( "map" ) , vec![ map_arg] ) ,
97+ ( mk( ) . path_segment( "collect" ) , vec![ ] ) ,
98+ ] ,
99+ ) ;
100+ mk ( ) . local ( mk ( ) . mutbl ( ) . ident_pat ( "args_strings" ) , Some ( ty) , Some ( init) )
101+ } ) ) ) ;
102+
103+ stmts. push ( mk ( ) . local_stmt ( Box :: new ( {
104+ // Vec<*mut ::core::ffi::c_char>
105+ let ty = mk ( ) . path_ty ( vec ! [ mk( ) . path_segment_with_args(
106+ "Vec" ,
107+ mk( ) . angle_bracketed_args( vec![ mk( )
108+ . mutbl( )
109+ . ptr_ty( mk( ) . abs_path_ty( vec![ "core" , "ffi" , "c_char" ] ) ) ] ) ,
110+ ) ] ) ;
111+ // |arg| arg.as_mut_ptr() as *mut ::core::ffi::c_char
112+ let map_arg = mk ( ) . closure_expr (
113+ CaptureBy :: Ref ,
114+ Movability :: Movable ,
115+ vec ! [ mk( ) . ident_pat( "arg" ) ] ,
116+ ReturnType :: Default ,
117+ mk ( ) . cast_expr (
118+ mk ( ) . method_call_expr ( mk ( ) . ident_expr ( "arg" ) , "as_mut_ptr" , vec ! [ ] ) ,
119+ mk ( ) . mutbl ( )
120+ . ptr_ty ( mk ( ) . abs_path_ty ( vec ! [ "core" , "ffi" , "c_char" ] ) ) ,
121+ ) ,
122+ ) ;
123+ // ::core::iter::once(::core::ptr::null_mut())
124+ let chain_arg = mk ( ) . call_expr (
125+ mk ( ) . abs_path_expr ( vec ! [ "core" , "iter" , "once" ] ) ,
126+ vec ! [ mk( ) . call_expr(
127+ mk( ) . abs_path_expr( vec![ "core" , "ptr" , "null_mut" ] ) ,
83128 vec![ ] ,
84129 ) ] ,
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- ) ) ) ;
130+ ) ;
131+ // args_strings
132+ // .iter_mut()
133+ // .map(map_arg)
134+ // .chain(chain_arg)
135+ // .collect()
136+ let init = mk ( ) . method_chain_expr (
137+ mk ( ) . ident_expr ( "args_strings" ) ,
138+ vec ! [
139+ ( mk( ) . path_segment( "iter_mut" ) , vec![ ] ) ,
140+ ( mk( ) . path_segment( "map" ) , vec![ map_arg] ) ,
141+ ( mk( ) . path_segment( "chain" ) , vec![ chain_arg] ) ,
142+ ( mk( ) . path_segment( "collect" ) , vec![ ] ) ,
143+ ] ,
144+ ) ;
145+ mk ( ) . local ( mk ( ) . mutbl ( ) . ident_pat ( "args_ptrs" ) , Some ( ty) , Some ( init) )
146+ } ) ) ) ;
95147
96148 let argc_ty: Box < Type > = match self . ast_context . index ( parameters[ 0 ] ) . kind {
97149 CDeclKind :: Variable { ref typ, .. } => self . convert_type ( typ. ctype ) ,
@@ -105,8 +157,7 @@ impl<'c> Translation<'c> {
105157 "Cannot find type of 'argv' argument in main function" ,
106158 ) ) ,
107159 } ?;
108-
109- let args = mk ( ) . ident_expr ( "args" ) ;
160+ let args = mk ( ) . ident_expr ( "args_ptrs" ) ;
110161 let argc = mk ( ) . binary_expr (
111162 BinOp :: Sub ( Default :: default ( ) ) ,
112163 mk ( ) . method_call_expr ( args. clone ( ) , "len" , no_args. clone ( ) ) ,
0 commit comments