Merge branch 'scanf' into 'master'
Scanf See merge request redox-os/relibc!277
This commit is contained in:
+4
-2
@@ -27,7 +27,8 @@ global_asm!(
|
||||
);
|
||||
// https://git.musl-libc.org/cgit/musl/tree/crt/aarch64/crti.s
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
global_asm!(r#"
|
||||
global_asm!(
|
||||
r#"
|
||||
.section .init
|
||||
.global _init
|
||||
.type _init,%function
|
||||
@@ -45,7 +46,8 @@ global_asm!(r#"
|
||||
mov x29,sp
|
||||
// stp: "stores two doublewords from the first and second argument to memory addressed by addr"
|
||||
// Body will be filled in by gcc and ended by crtn.o
|
||||
"#);
|
||||
"#
|
||||
);
|
||||
|
||||
#[panic_handler]
|
||||
#[linkage = "weak"]
|
||||
|
||||
+4
-2
@@ -23,7 +23,8 @@ global_asm!(
|
||||
);
|
||||
// https://git.musl-libc.org/cgit/musl/tree/crt/aarch64/crtn.s
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
global_asm!(r#"
|
||||
global_asm!(
|
||||
r#"
|
||||
.section .init
|
||||
// This happens after crti.o and gcc has inserted code
|
||||
// ldp: "loads two doublewords from memory addressed by the third argument to the first and second"
|
||||
@@ -35,7 +36,8 @@ global_asm!(r#"
|
||||
// ldp: "loads two doublewords from memory addressed by the third argument to the first and second"
|
||||
ldp x29,x30,[sp],#16
|
||||
ret
|
||||
"#);
|
||||
"#
|
||||
);
|
||||
|
||||
#[panic_handler]
|
||||
#[linkage = "weak"]
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
use super::{fseek_locked, ftell_locked, FILE, SEEK_SET};
|
||||
use crate::core_io::Read;
|
||||
struct LookAheadBuffer {
|
||||
buf: *const u8,
|
||||
pos: isize,
|
||||
look_ahead: isize,
|
||||
}
|
||||
impl LookAheadBuffer {
|
||||
fn look_ahead(&mut self) -> Result<Option<u8>, i32> {
|
||||
let byte = unsafe { *self.buf.offset(self.look_ahead) };
|
||||
self.look_ahead += 1;
|
||||
Ok(Some(byte))
|
||||
}
|
||||
|
||||
fn commit(&mut self) {
|
||||
self.pos = self.look_ahead;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<*const u8> for LookAheadBuffer {
|
||||
fn from(buff: *const u8) -> LookAheadBuffer {
|
||||
LookAheadBuffer {
|
||||
buf: buff,
|
||||
pos: 0,
|
||||
look_ahead: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LookAheadFile<'a> {
|
||||
f: &'a mut FILE,
|
||||
look_ahead: i64,
|
||||
}
|
||||
|
||||
impl<'a> LookAheadFile<'a> {
|
||||
fn look_ahead(&mut self) -> Result<Option<u8>, i32> {
|
||||
let buf = &mut [0];
|
||||
let seek = unsafe { ftell_locked(self.f) };
|
||||
unsafe { fseek_locked(self.f, self.look_ahead, SEEK_SET) };
|
||||
let ret = match self.f.read(buf) {
|
||||
Ok(0) => Ok(None),
|
||||
Ok(_) => Ok(Some(buf[0])),
|
||||
Err(_) => Err(-1),
|
||||
};
|
||||
unsafe { fseek_locked(self.f, seek, SEEK_SET) };
|
||||
self.look_ahead += 1;
|
||||
ret
|
||||
}
|
||||
|
||||
fn commit(&mut self) {
|
||||
unsafe { fseek_locked(self.f, self.look_ahead, SEEK_SET) };
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a mut FILE> for LookAheadFile<'a> {
|
||||
fn from(f: &'a mut FILE) -> LookAheadFile<'a> {
|
||||
let look_ahead = unsafe { ftell_locked(f) } as i64;
|
||||
LookAheadFile { f, look_ahead }
|
||||
}
|
||||
}
|
||||
|
||||
enum LookAheadReaderEnum<'a> {
|
||||
FILE(LookAheadFile<'a>),
|
||||
// (buffer, location)
|
||||
BUFFER(LookAheadBuffer),
|
||||
}
|
||||
|
||||
pub struct LookAheadReader<'a>(LookAheadReaderEnum<'a>);
|
||||
|
||||
impl<'a> LookAheadReader<'a> {
|
||||
pub fn lookahead1(&mut self) -> Result<Option<u8>, i32> {
|
||||
match &mut self.0 {
|
||||
LookAheadReaderEnum::FILE(f) => f.look_ahead(),
|
||||
LookAheadReaderEnum::BUFFER(b) => b.look_ahead(),
|
||||
}
|
||||
}
|
||||
pub fn commit(&mut self) {
|
||||
match &mut self.0 {
|
||||
LookAheadReaderEnum::FILE(f) => f.commit(),
|
||||
LookAheadReaderEnum::BUFFER(b) => b.commit(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a mut FILE> for LookAheadReader<'a> {
|
||||
fn from(f: &'a mut FILE) -> LookAheadReader {
|
||||
LookAheadReader(LookAheadReaderEnum::FILE(f.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<*const u8> for LookAheadReader<'a> {
|
||||
fn from(buff: *const u8) -> LookAheadReader<'a> {
|
||||
LookAheadReader(LookAheadReaderEnum::BUFFER(buff.into()))
|
||||
}
|
||||
}
|
||||
+15
-10
@@ -39,9 +39,10 @@ mod getdelim;
|
||||
|
||||
mod ext;
|
||||
mod helpers;
|
||||
mod lookaheadreader;
|
||||
mod printf;
|
||||
mod scanf;
|
||||
|
||||
use lookaheadreader::LookAheadReader;
|
||||
static mut TMPNAM_BUF: [c_char; L_tmpnam as usize + 1] = [0; L_tmpnam as usize + 1];
|
||||
|
||||
enum Buffer<'a> {
|
||||
@@ -514,9 +515,12 @@ pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int)
|
||||
|
||||
/// Seek to an offset `offset` from `whence`
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn fseeko(stream: *mut FILE, mut off: off_t, whence: c_int) -> c_int {
|
||||
pub unsafe extern "C" fn fseeko(stream: *mut FILE, off: off_t, whence: c_int) -> c_int {
|
||||
let mut stream = (*stream).lock();
|
||||
fseek_locked(&mut *stream, off, whence)
|
||||
}
|
||||
|
||||
pub unsafe fn fseek_locked(stream: &mut FILE, mut off: off_t, whence: c_int) -> c_int {
|
||||
if whence == SEEK_CUR {
|
||||
// Since it's a buffered writer, our actual cursor isn't where the user
|
||||
// thinks
|
||||
@@ -555,7 +559,10 @@ pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
|
||||
/// Get the current position of the cursor in the file
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ftello(stream: *mut FILE) -> off_t {
|
||||
let stream = (*stream).lock();
|
||||
let mut stream = (*stream).lock();
|
||||
ftell_locked(&mut *stream)
|
||||
}
|
||||
pub unsafe extern "C" fn ftell_locked(stream: &mut FILE) -> off_t {
|
||||
let pos = Sys::lseek(*stream.file, 0, SEEK_CUR);
|
||||
if pos < 0 {
|
||||
return -1;
|
||||
@@ -1043,9 +1050,10 @@ pub unsafe extern "C" fn vsprintf(s: *mut c_char, format: *const c_char, ap: va_
|
||||
pub unsafe extern "C" fn vfscanf(file: *mut FILE, format: *const c_char, ap: va_list) -> c_int {
|
||||
let ret = {
|
||||
let mut file = (*file).lock();
|
||||
scanf::scanf(&mut *file, format, ap)
|
||||
let f: &mut FILE = &mut *file;
|
||||
let reader: LookAheadReader = f.into();
|
||||
scanf::scanf(reader, format, ap)
|
||||
};
|
||||
fseeko(file, -1, SEEK_CUR);
|
||||
ret
|
||||
}
|
||||
|
||||
@@ -1056,9 +1064,6 @@ pub unsafe extern "C" fn vscanf(format: *const c_char, ap: va_list) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn vsscanf(s: *const c_char, format: *const c_char, ap: va_list) -> c_int {
|
||||
scanf::scanf(
|
||||
&mut platform::UnsafeStringReader(s as *const u8),
|
||||
format,
|
||||
ap,
|
||||
)
|
||||
let reader = (s as *const u8).into();
|
||||
scanf::scanf(reader, format, ap)
|
||||
}
|
||||
|
||||
+24
-13
@@ -1,4 +1,5 @@
|
||||
use crate::{io::Read, platform::types::*};
|
||||
use super::lookaheadreader::LookAheadReader;
|
||||
use crate::platform::types::*;
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::ffi::VaList as va_list;
|
||||
|
||||
@@ -25,8 +26,8 @@ unsafe fn next_byte(string: &mut *const c_char) -> Result<u8, c_int> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn inner_scanf<R: Read>(
|
||||
mut r: R,
|
||||
unsafe fn inner_scanf(
|
||||
mut r: LookAheadReader,
|
||||
mut format: *const c_char,
|
||||
mut ap: va_list,
|
||||
) -> Result<c_int, c_int> {
|
||||
@@ -37,15 +38,14 @@ unsafe fn inner_scanf<R: Read>(
|
||||
|
||||
macro_rules! read {
|
||||
() => {{
|
||||
let buf = &mut [byte];
|
||||
match r.read(buf) {
|
||||
Ok(0) => false,
|
||||
Ok(_) => {
|
||||
byte = buf[0];
|
||||
match r.lookahead1() {
|
||||
Ok(None) => false,
|
||||
Ok(Some(b)) => {
|
||||
byte = b;
|
||||
count += 1;
|
||||
true
|
||||
}
|
||||
Err(_) => return Err(-1),
|
||||
Err(x) => return Err(x),
|
||||
}
|
||||
}};
|
||||
}
|
||||
@@ -59,7 +59,10 @@ unsafe fn inner_scanf<R: Read>(
|
||||
};
|
||||
(inner $($placeholder:expr)*) => {
|
||||
if !skip_read && !read!() {
|
||||
return Ok(matched);
|
||||
match matched {
|
||||
0 => return Ok(-1),
|
||||
a => return Ok(a),
|
||||
}
|
||||
}
|
||||
$(else {
|
||||
// Hacky way of having this optional
|
||||
@@ -86,6 +89,7 @@ unsafe fn inner_scanf<R: Read>(
|
||||
if c != byte {
|
||||
return Ok(matched);
|
||||
}
|
||||
r.commit();
|
||||
} else {
|
||||
c = next_byte(&mut format)?;
|
||||
|
||||
@@ -215,6 +219,7 @@ unsafe fn inner_scanf<R: Read>(
|
||||
dot = true;
|
||||
}
|
||||
n.push(byte as char);
|
||||
r.commit();
|
||||
width = width.map(|w| w - 1);
|
||||
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
|
||||
return Ok(matched);
|
||||
@@ -344,6 +349,7 @@ unsafe fn inner_scanf<R: Read>(
|
||||
if let Some(ptr) = ptr {
|
||||
*ptr = 0;
|
||||
matched += 1;
|
||||
r.commit();
|
||||
}
|
||||
}
|
||||
b'c' => {
|
||||
@@ -362,6 +368,7 @@ unsafe fn inner_scanf<R: Read>(
|
||||
|
||||
if ptr.is_some() {
|
||||
matched += 1;
|
||||
r.commit();
|
||||
}
|
||||
}
|
||||
b'[' => {
|
||||
@@ -402,12 +409,15 @@ unsafe fn inner_scanf<R: Read>(
|
||||
let mut ptr: Option<*mut c_char> = if ignore { None } else { Some(ap.arg()) };
|
||||
|
||||
// While we haven't used up all the width, and it matches
|
||||
let mut data_stored = false;
|
||||
while width.map(|w| w > 0).unwrap_or(true) && !invert == matches.contains(&byte)
|
||||
{
|
||||
if let Some(ref mut ptr) = ptr {
|
||||
**ptr = byte as c_char;
|
||||
*ptr = ptr.offset(1);
|
||||
data_stored = true;
|
||||
}
|
||||
r.commit();
|
||||
// Decrease the width, and read a new character unless the width is 0
|
||||
width = width.map(|w| w - 1);
|
||||
if width.map(|w| w > 0).unwrap_or(true) && !read!() {
|
||||
@@ -418,8 +428,8 @@ unsafe fn inner_scanf<R: Read>(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ptr) = ptr {
|
||||
*ptr = 0;
|
||||
if data_stored {
|
||||
*ptr.unwrap() = 0;
|
||||
matched += 1;
|
||||
}
|
||||
}
|
||||
@@ -444,7 +454,8 @@ unsafe fn inner_scanf<R: Read>(
|
||||
}
|
||||
Ok(matched)
|
||||
}
|
||||
pub unsafe fn scanf<R: Read>(r: R, format: *const c_char, ap: va_list) -> c_int {
|
||||
|
||||
pub unsafe fn scanf(r: LookAheadReader, format: *const c_char, ap: va_list) -> c_int {
|
||||
match inner_scanf(r, format, ap) {
|
||||
Ok(n) => n,
|
||||
Err(n) => n,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use core::slice;
|
||||
|
||||
use crate::platform::{Pal, Sys, types::*};
|
||||
use crate::platform::{types::*, Pal, Sys};
|
||||
|
||||
pub const GRND_NONBLOCK: c_uint = 1;
|
||||
pub const GRND_RANDOM: c_uint = 2;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn getrandom(buf: *mut c_void, buflen: size_t, flags: c_uint) -> ssize_t {
|
||||
Sys::getrandom(slice::from_raw_parts_mut(
|
||||
buf as *mut u8,
|
||||
buflen as usize
|
||||
), flags)
|
||||
Sys::getrandom(
|
||||
slice::from_raw_parts_mut(buf as *mut u8, buflen as usize),
|
||||
flags,
|
||||
)
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,10 +26,10 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
access,
|
||||
debug::{RTLDDebug, RTLDState, _dl_debug_state, _r_debug},
|
||||
tcb::{Master, Tcb},
|
||||
PAGE_SIZE,
|
||||
access,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
|
||||
+3
-7
@@ -1,11 +1,7 @@
|
||||
use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader};
|
||||
|
||||
use self::tcb::{Master, Tcb};
|
||||
use crate::{
|
||||
start::Stack,
|
||||
c_str::CStr,
|
||||
platform::types::*
|
||||
};
|
||||
use crate::{c_str::CStr, platform::types::*, start::Stack};
|
||||
pub const PAGE_SIZE: usize = 4096;
|
||||
|
||||
pub mod debug;
|
||||
@@ -85,8 +81,8 @@ pub fn static_init(sp: &'static Stack) {
|
||||
|
||||
// Wrapper over the systemcall, Do not use outside of ld_so
|
||||
pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
|
||||
let path = CStr::from_ptr(path);
|
||||
syscall!(ACCESS, (path).as_ptr(), mode) as c_int
|
||||
let path = CStr::from_ptr(path);
|
||||
syscall!(ACCESS, (path).as_ptr(), mode) as c_int
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
//! compatibility. So, this module will be a hellhole.
|
||||
|
||||
use super::super::{errno, types::*, Pal, PalPtrace, PalSignal, Sys};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::header::arch_aarch64_user::user_regs_struct;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::header::arch_x64_user::user_regs_struct;
|
||||
use crate::{
|
||||
c_str::CString,
|
||||
fs::File,
|
||||
@@ -12,10 +16,6 @@ use crate::{
|
||||
io::{self, prelude::*},
|
||||
sync::{Mutex, Once},
|
||||
};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use crate::header::arch_aarch64_user::user_regs_struct;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::header::arch_x64_user::user_regs_struct;
|
||||
|
||||
use alloc::collections::{btree_map::Entry, BTreeMap};
|
||||
use core::mem;
|
||||
|
||||
@@ -143,7 +143,10 @@ unsafe fn inner_get_name(
|
||||
inner_af_unix(&buf[5..], address, address_len);
|
||||
} else {
|
||||
// Socket doesn't belong to any scheme
|
||||
panic!("socket {:?} doesn't match either tcp, udp or chan schemes", str::from_utf8(buf));
|
||||
panic!(
|
||||
"socket {:?} doesn't match either tcp, udp or chan schemes",
|
||||
str::from_utf8(buf)
|
||||
);
|
||||
}
|
||||
|
||||
Ok(0)
|
||||
|
||||
@@ -68,12 +68,14 @@ fn clock_gettime() {
|
||||
|
||||
#[test]
|
||||
fn getrandom() {
|
||||
use crate::header::sys_random;
|
||||
use crate::platform::types::ssize_t;
|
||||
use crate::{header::sys_random, platform::types::ssize_t};
|
||||
|
||||
let mut arrays = [[0; 32]; 32];
|
||||
for i in 1..arrays.len() {
|
||||
assert_eq!(Sys::getrandom(&mut arrays[i], 0), arrays[i].len() as ssize_t);
|
||||
assert_eq!(
|
||||
Sys::getrandom(&mut arrays[i], 0),
|
||||
arrays[i].len() as ssize_t
|
||||
);
|
||||
|
||||
for j in 0..arrays.len() {
|
||||
if i != j {
|
||||
|
||||
@@ -45,6 +45,7 @@ EXPECT_NAMES=\
|
||||
stdio/ungetc_multiple \
|
||||
stdio/ungetc_ftell \
|
||||
stdio/fscanf_offby1 \
|
||||
stdio/fscanf \
|
||||
stdio/printf_neg_pad \
|
||||
stdlib/a64l \
|
||||
stdlib/alloc \
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
1 2 3 9
|
||||
9
|
||||
16
|
||||
35
|
||||
48
|
||||
92
|
||||
109
|
||||
152
|
||||
201
|
||||
241
|
||||
276
|
||||
293
|
||||
299
|
||||
301
|
||||
@@ -1,14 +1,14 @@
|
||||
1, { sa: 12, ia: 0, ib: 0, ic: 0, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
|
||||
2, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
|
||||
0, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 18, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: Hello, string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 15, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: a, string1: Hello, string2: , string3: , string4: }
|
||||
2, { sa: 12, ia: 15, ib: 837, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: elllo, string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: elllo, string2: , string3: , string4: }
|
||||
0, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: elllo, string2: , string3: , string4: }
|
||||
4, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: e, string2: o, string3: l, string4: d }
|
||||
4, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: a, string2: e, string3: f, string4: dddddd }
|
||||
4, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: a, string2: e, string3: f, string4: dddddd }
|
||||
1, { sa: 12, ia: 0, ib: 8, ic: 0, fa: 0.100000, da: 0.000000, ptr: (nil), char: h, string1: testbbbb, string2: e, string3: f, string4: dddddd }
|
||||
2, { sa: 12, ia: 345, ib: 0, ic: 0, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
|
||||
3, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.000000, da: 0.000000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
|
||||
2, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: (nil), char: a, string1: , string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: a, string1: , string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 18, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: a, string1: Hello, string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 15, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: a, string1: Hello, string2: , string3: , string4: }
|
||||
2, { sa: 12, ia: 15, ib: 837, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string1: elllo, string2: , string3: , string4: }
|
||||
1, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string1: elllo, string2: , string3: , string4: }
|
||||
0, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string1: elllo, string2: , string3: , string4: }
|
||||
4, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string1: e, string2: o, string3: l, string4: d }
|
||||
4, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string1: a, string2: e, string3: f, string4: dddddd }
|
||||
4, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string1: a, string2: e, string3: f, string4: dddddd }
|
||||
1, { sa: 12, ia: 0, ib: 8, ic: 8, fa: 0.100000, da: 0.200000, ptr: 0xabcdef, char: h, string1: testbbbb, string2: e, string3: f, string4: dddddd }
|
||||
3 "https" "//" "redox-os.org" ""
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
//@ 1 2 3
|
||||
//@ SS
|
||||
#include <stdio.h>
|
||||
int main() {
|
||||
FILE *f = fopen("stdio/fscanf.c", "r");
|
||||
int x, y, z;
|
||||
fscanf(f, "//@ %d %d %d",&x , &y, &z);
|
||||
printf("%d %d %d %ld\n", x, y, z, ftell(f));
|
||||
while(-1 != fscanf(f, "%*[^\n]")) {
|
||||
printf("%ld\n", ftell(f));
|
||||
getc(f);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user