Skip to content

Migrating from 2021 edition to 2024 #405

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ members = [
[workspace.package]
repository = "https://github.com/rustcoreutils/posixutils-rs"
license = "MIT"
edition = "2021"
rust-version = "1.84.0"
edition = "2024"
rust-version = "1.85.0"

[workspace.dependencies]
clap = { version = "4", default-features = false, features = ["std", "derive", "help", "usage", "error-context", "cargo"] }
Expand Down
6 changes: 3 additions & 3 deletions awk/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ use crate::program::{
};
use crate::regex::Regex;

use pest::Parser;
use pest::error::InputLocation;
use pest::iterators::{Pair, Pairs};
use pest::pratt_parser::{Assoc, Op, PrattParser};
use pest::Parser;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::ffi::CString;
Expand Down Expand Up @@ -704,13 +704,13 @@ impl Compiler {
return Err(pest_error_from_span(
span,
format!("'{}' is not a function", name),
))
));
}
None => {
return Err(pest_error_from_span(
span,
format!("call to undefined function '{}'", name),
))
));
}
}
Ok(Expr::new(ExprKind::Number, instructions))
Expand Down
2 changes: 1 addition & 1 deletion awk/src/interpreter/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//

use std::{
collections::{hash_map::Entry, HashMap},
collections::{HashMap, hash_map::Entry},
rc::Rc,
};

Expand Down
6 changes: 3 additions & 3 deletions awk/src/interpreter/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

use core::panic;
use std::{
collections::{hash_map::Entry, HashMap},
collections::{HashMap, hash_map::Entry},
ffi::CString,
fs::File,
io::{BufReader, Bytes, Read, Write},
Expand Down Expand Up @@ -43,13 +43,13 @@ impl TryFrom<AwkString> for RecordSeparator {
type ReadResult = Result<u8, String>;

macro_rules! read_iter_next {
($iter:expr, $ret:expr) => {
($iter:expr_2021, $ret:expr_2021) => {
match $iter.next() {
Some(byte_result) => byte_result?,
None => return $ret,
}
};
($iter:expr) => {
($iter:expr_2021) => {
read_iter_next!($iter, Ok(None))
};
}
Expand Down
174 changes: 91 additions & 83 deletions awk/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ use crate::program::{
};
use crate::regex::Regex;
use format::{
fmt_write_decimal_float, fmt_write_float_general, fmt_write_hex_float,
IntegerFormat, fmt_write_decimal_float, fmt_write_float_general, fmt_write_hex_float,
fmt_write_scientific_float, fmt_write_signed, fmt_write_string, fmt_write_unsigned,
parse_conversion_specifier_args, IntegerFormat,
parse_conversion_specifier_args,
};
use std::cell::{RefCell, UnsafeCell};
use std::collections::HashMap;
Expand All @@ -44,11 +44,7 @@ mod string;
const STACK_SIZE: usize = 2048;

fn bool_to_f64(p: bool) -> f64 {
if p {
1.0
} else {
0.0
}
if p { 1.0 } else { 0.0 }
}

fn strtod(s: &str) -> f64 {
Expand Down Expand Up @@ -410,7 +406,7 @@ fn call_simple_builtin(
stack.push_value(value.to_uppercase())?;
}
BuiltinFunction::Gsub | BuiltinFunction::Sub => {
return builtin_gsub(stack, global_env, function == BuiltinFunction::Sub)
return builtin_gsub(stack, global_env, function == BuiltinFunction::Sub);
}
BuiltinFunction::System => {
let command: CString = stack
Expand Down Expand Up @@ -588,61 +584,65 @@ impl Record {
last_field: usize,
truncate_fields: bool,
) -> Result<(), String> {
let last_field = if truncate_fields {
if last_field < *self.last_field.borrow() {
for field in self
.fields
.iter()
.skip(last_field + 1)
.take(*self.last_field.borrow() - last_field)
{
(*field.get()).value = AwkValueVariant::UninitializedScalar;
unsafe {
let last_field = if truncate_fields {
if last_field < *self.last_field.borrow() {
for field in self
.fields
.iter()
.skip(last_field + 1)
.take(*self.last_field.borrow() - last_field)
{
(*field.get()).value = AwkValueVariant::UninitializedScalar;
}
}
last_field
} else {
self.last_field.borrow().max(last_field)
};
let mut new_record = String::new();
for field in self.fields.iter().skip(1).take(last_field - 1) {
let field_str = (*field.get())
.clone()
.scalar_to_string(&global_env.convfmt)?;
write!(new_record, "{}{}", field_str, &global_env.ofs)
.expect("error writing to string");
}
last_field
} else {
self.last_field.borrow().max(last_field)
};
let mut new_record = String::new();
for field in self.fields.iter().skip(1).take(last_field - 1) {
let field_str = (*field.get())
let last_field_str = (*self.fields[last_field].get())
.clone()
.scalar_to_string(&global_env.convfmt)?;
write!(new_record, "{}{}", field_str, &global_env.ofs)
.expect("error writing to string");
}
let last_field_str = (*self.fields[last_field].get())
.clone()
.scalar_to_string(&global_env.convfmt)?;
write!(new_record, "{}", last_field_str).expect("error writing to string");
// the spec doesn't specify if a recomputed record should be a numeric string.
// Most other implementations don't really handle this case. Here we just
// mark it as a numeric string if appropriate
let record_str = maybe_numeric_string(new_record);
*self.fields[0].get() = AwkValue::field_ref(record_str.clone(), 0);
*self.record.borrow_mut() = record_str.try_into()?;
*self.last_field.borrow_mut() = last_field;
Ok(())
write!(new_record, "{}", last_field_str).expect("error writing to string");
// the spec doesn't specify if a recomputed record should be a numeric string.
// Most other implementations don't really handle this case. Here we just
// mark it as a numeric string if appropriate
let record_str = maybe_numeric_string(new_record);
*self.fields[0].get() = AwkValue::field_ref(record_str.clone(), 0);
*self.record.borrow_mut() = record_str.try_into()?;
*self.last_field.borrow_mut() = last_field;
Ok(())
}
}

/// # Safety
/// The caller has to ensure that there are no active references to the fields
unsafe fn recompute_fields(&self, global_env: &GlobalEnv) -> Result<(), String> {
let mut last_field = 0;
let record_str = (*self.fields[0].get())
.to_owned()
.scalar_to_string(&global_env.convfmt)?;
split_record(record_str.clone(), &global_env.fs, |i, s| {
let field_index = i + 1;
last_field += 1;
*self.fields[field_index].get() = AwkValue::field_ref(s, field_index as u16);
unsafe {
let mut last_field = 0;
let record_str = (*self.fields[0].get())
.to_owned()
.scalar_to_string(&global_env.convfmt)?;
split_record(record_str.clone(), &global_env.fs, |i, s| {
let field_index = i + 1;
last_field += 1;
*self.fields[field_index].get() = AwkValue::field_ref(s, field_index as u16);
Ok(())
})
.expect("error splitting record");
*self.fields[0].get() = AwkValue::field_ref(record_str.clone(), 0);
*self.record.borrow_mut() = record_str.try_into()?;
*self.last_field.borrow_mut() = last_field;
Ok(())
})
.expect("error splitting record");
*self.fields[0].get() = AwkValue::field_ref(record_str.clone(), 0);
*self.record.borrow_mut() = record_str.try_into()?;
*self.last_field.borrow_mut() = last_field;
Ok(())
}
}

fn get_last_field(&self) -> usize {
Expand Down Expand Up @@ -920,16 +920,18 @@ impl StackValue {
/// # Safety
/// the caller has to ensure that the value is valid and dereferencable
unsafe fn value_ref(&mut self) -> &mut AwkValue {
match self {
StackValue::Value(val) => val.get_mut(),
StackValue::ValueRef(val_ref) => &mut **val_ref,
StackValue::UninitializedRef(val_ref) => &mut **val_ref,
StackValue::ArrayElementRef(array_element_ref) => (*array_element_ref.array)
.as_array()
.expect("expected array")
.index_to_value(array_element_ref.value_index)
.expect("invalid array value index"),
_ => unreachable!("invalid stack value"),
unsafe {
match self {
StackValue::Value(val) => val.get_mut(),
StackValue::ValueRef(val_ref) => &mut **val_ref,
StackValue::UninitializedRef(val_ref) => &mut **val_ref,
StackValue::ArrayElementRef(array_element_ref) => (*array_element_ref.array)
.as_array()
.expect("expected array")
.index_to_value(array_element_ref.value_index)
.expect("invalid array value index"),
_ => unreachable!("invalid stack value"),
}
}
}

Expand Down Expand Up @@ -962,29 +964,33 @@ impl StackValue {
/// # Safety
/// pointers inside the `StackValue` have to be valid and dereferencable
unsafe fn into_owned(self) -> AwkValue {
match self {
StackValue::Value(val) => val.into_inner(),
StackValue::ValueRef(ref_val) => (*ref_val).clone().into_ref(AwkRefType::None),
StackValue::UninitializedRef(_) => AwkValue::uninitialized_scalar(),
_ => unreachable!("invalid stack value"),
unsafe {
match self {
StackValue::Value(val) => val.into_inner(),
StackValue::ValueRef(ref_val) => (*ref_val).clone().into_ref(AwkRefType::None),
StackValue::UninitializedRef(_) => AwkValue::uninitialized_scalar(),
_ => unreachable!("invalid stack value"),
}
}
}

/// # Safety
/// pointers inside the `StackValue` have to be valid and dereferencable
unsafe fn ensure_value_is_scalar(&mut self) -> Result<(), String> {
self.value_ref().ensure_value_is_scalar()
unsafe { self.value_ref().ensure_value_is_scalar() }
}

/// # Safety
/// `value` has to be a valid pointer at least until the value preceding it
/// on the stack is popped
unsafe fn from_var(value: *mut AwkValue) -> Self {
let value_ref = &mut *value;
match value_ref.value {
AwkValueVariant::Array(_) => StackValue::ValueRef(value),
AwkValueVariant::Uninitialized => StackValue::UninitializedRef(value),
_ => StackValue::Value(UnsafeCell::new(value_ref.clone())),
unsafe {
let value_ref = &mut *value;
match value_ref.value {
AwkValueVariant::Array(_) => StackValue::ValueRef(value),
AwkValueVariant::Uninitialized => StackValue::UninitializedRef(value),
_ => StackValue::Value(UnsafeCell::new(value_ref.clone())),
}
}
}

Expand Down Expand Up @@ -1061,12 +1067,14 @@ impl<'i, 's> Stack<'i, 's> {
/// # Safety
/// `value` has to be valid at least until the value preceding it is popped
unsafe fn push(&mut self, value: StackValue) -> Result<(), String> {
if self.sp == self.stack_end {
Err("stack overflow".to_string())
} else {
*self.sp = value;
self.sp = self.sp.add(1);
Ok(())
unsafe {
if self.sp == self.stack_end {
Err("stack overflow".to_string())
} else {
*self.sp = value;
self.sp = self.sp.add(1);
Ok(())
}
}
}

Expand Down Expand Up @@ -1116,7 +1124,7 @@ impl<'i, 's> Stack<'i, 's> {
/// `value_ptr` has to be safe to access at least until the value preceding it
/// on the stack is popped.
unsafe fn push_ref(&mut self, value_ptr: *mut AwkValue) -> Result<(), String> {
self.push(StackValue::ValueRef(value_ptr))
unsafe { self.push(StackValue::ValueRef(value_ptr)) }
}

fn next_instruction(&mut self) -> Option<OpCode> {
Expand Down Expand Up @@ -1207,15 +1215,15 @@ struct Interpreter {
}

macro_rules! numeric_op {
($stack:expr, $op:tt) => {
($stack:expr_2021, $op:tt) => {
let rhs = $stack.pop_scalar_value()?.scalar_as_f64();
let lhs = $stack.pop_scalar_value()?.scalar_as_f64();
$stack.push_value(lhs $op rhs)?;
};
}

macro_rules! compare_op {
($stack:expr, $convfmt:expr, $op:tt) => {
($stack:expr_2021, $convfmt:expr_2021, $op:tt) => {
let rhs = $stack.pop_scalar_value()?;
let lhs = $stack.pop_scalar_value()?;
match (&lhs.value, &rhs.value) {
Expand Down
2 changes: 1 addition & 1 deletion awk/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::compiler::compile_program;
use crate::interpreter::interpret;
use clap::Parser;
use compiler::SourceFile;
use gettextrs::{bind_textdomain_codeset, gettext, setlocale, textdomain, LocaleCategory};
use gettextrs::{LocaleCategory, bind_textdomain_codeset, gettext, setlocale, textdomain};
use std::error::Error;
use std::fmt::Display;
use std::io::Read;
Expand Down
Loading