Compare commits
33 Commits
2f805cc942
...
stris
| Author | SHA1 | Date | |
|---|---|---|---|
|
ee9d5be015
|
|||
|
28f6d2508f
|
|||
|
cbf5032a22
|
|||
|
7d5443dee6
|
|||
|
f9c84179fe
|
|||
|
72c3ac5df0
|
|||
|
1796e772fb
|
|||
|
e0c985f7ff
|
|||
|
4c81516742
|
|||
|
98c4d94f6d
|
|||
|
da190f713c
|
|||
|
10b7f7706b
|
|||
|
b1a4a1a2b9
|
|||
|
a693ced9d9
|
|||
|
1003c82d23
|
|||
|
baa75a2619
|
|||
|
d6d9c2088e
|
|||
|
ea2efdf5b9
|
|||
|
6c558654f3
|
|||
|
8699d04ccc
|
|||
|
18dfd20937
|
|||
|
42010596de
|
|||
|
0ddfa6e474
|
|||
|
326c8f77d1
|
|||
|
72ef8d00bc
|
|||
|
851f729ebd
|
|||
|
e253cdf79c
|
|||
|
d89707a47c
|
|||
|
2a75b8f820
|
|||
|
bda7c074b0
|
|||
|
7c9f640ee1
|
|||
|
3910c341bd
|
|||
|
cfef7aec1d
|
10
Makefile
10
Makefile
@@ -42,7 +42,7 @@ BIN = build/bin
|
|||||||
default: all test
|
default: all test
|
||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: dj false fop hru intcmp mm npc rpn scrut str strcmp swab true
|
all: dj false fop hru intcmp mm npc rpn scrut strcmp stris swab true
|
||||||
|
|
||||||
# keep build/include until bindgen(1) has stdin support
|
# keep build/include until bindgen(1) has stdin support
|
||||||
# https://github.com/rust-lang/rust-bindgen/issues/2703
|
# https://github.com/rust-lang/rust-bindgen/issues/2703
|
||||||
@@ -147,10 +147,10 @@ scrut: build/bin/scrut
|
|||||||
build/bin/scrut: src/scrut.c build
|
build/bin/scrut: src/scrut.c build
|
||||||
$(CC) $(CFLAGS) -o $@ src/scrut.c
|
$(CC) $(CFLAGS) -o $@ src/scrut.c
|
||||||
|
|
||||||
.PHONY: str
|
.PHONY: stris
|
||||||
str: build/bin/str
|
stris: build/bin/stris
|
||||||
build/bin/str: src/str.c build
|
build/bin/stris: src/stris.rs build rustlibs
|
||||||
$(CC) $(CFLAGS) -o $@ src/str.c
|
$(RUSTC) $(RUSTFLAGS) -o $@ src/stris.rs
|
||||||
|
|
||||||
.PHONY: strcmp
|
.PHONY: strcmp
|
||||||
strcmp: build/bin/strcmp
|
strcmp: build/bin/strcmp
|
||||||
|
|||||||
59
docs/str.1
59
docs/str.1
@@ -1,59 +0,0 @@
|
|||||||
.\" Copyright (c) 2023–2024 DTB <trinity@trinity.moe>
|
|
||||||
.\" Copyright (c) 2023–2024 Emma Tebibyte <emma@tebibyte.media>
|
|
||||||
.\"
|
|
||||||
.\" This work is licensed under CC BY-SA 4.0. To see a copy of this license,
|
|
||||||
.\" visit <http://creativecommons.org/licenses/by-sa/4.0/>.
|
|
||||||
.\"
|
|
||||||
.TH STR 1 2024-06-17 "Harakit X.X.X"
|
|
||||||
.SH NAME
|
|
||||||
str \(en test string arguments
|
|
||||||
.\"
|
|
||||||
.SH SYNOPSIS
|
|
||||||
|
|
||||||
str
|
|
||||||
.B type string...
|
|
||||||
.\"
|
|
||||||
.SH DESCRIPTION
|
|
||||||
|
|
||||||
Test the character types of string arguments.
|
|
||||||
|
|
||||||
The tests in this program are equivalent to the functions with the same names in
|
|
||||||
.BR ctype.h (0p)
|
|
||||||
and are the methods by which string arguments are tested.
|
|
||||||
.\"
|
|
||||||
.SH DIAGNOSTICS
|
|
||||||
|
|
||||||
If all tests pass, the program will exit successfully. If any of the tests fail,
|
|
||||||
the program will exit unsuccessfully with an error code of 1.
|
|
||||||
|
|
||||||
When invoked incorrectly, a debug message will be printed and the program will
|
|
||||||
exit with the appropriate
|
|
||||||
.BR sysexits.h (3)
|
|
||||||
error code.
|
|
||||||
.\"
|
|
||||||
.SH CAVEATS
|
|
||||||
|
|
||||||
None of an empty string\(cqs contents pass any of the tests, so the program will
|
|
||||||
exit unsuccessfully if one is specified.
|
|
||||||
|
|
||||||
There\(cqs no way of knowing which argument failed the test without re-testing
|
|
||||||
arguments individually.
|
|
||||||
|
|
||||||
If a character in a string isn\(cqt valid ASCII, the program will exit
|
|
||||||
unsuccessfully.
|
|
||||||
.\"
|
|
||||||
.SH AUTHOR
|
|
||||||
|
|
||||||
Written by DTB
|
|
||||||
.MT trinity@trinity.moe
|
|
||||||
.ME .
|
|
||||||
.\"
|
|
||||||
.SH COPYRIGHT
|
|
||||||
|
|
||||||
Copyright \(co 2023 DTB. License AGPLv3+: GNU AGPL version 3 or later
|
|
||||||
<https://gnu.org/licenses/gpl.html>.
|
|
||||||
.\"
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR ctype (3p),
|
|
||||||
.BR strcmp(1),
|
|
||||||
.BR ascii(7)
|
|
||||||
104
docs/stris.1
Normal file
104
docs/stris.1
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
.\" Copyright (c) 2023–2024 DTB <trinity@trinity.moe>
|
||||||
|
.\" Copyright (c) 2023–2024 Emma Tebibyte <emma@tebibyte.media>
|
||||||
|
.\"
|
||||||
|
.\" This work is licensed under CC BY-SA 4.0. To see a copy of this license,
|
||||||
|
.\" visit <http://creativecommons.org/licenses/by-sa/4.0/>.
|
||||||
|
.\"
|
||||||
|
.TH STRIS 1 2024-10-22 "Harakit X.X.X"
|
||||||
|
.SH NAME
|
||||||
|
stris \(en test the character types of string arguments
|
||||||
|
.\"
|
||||||
|
.SH SYNOPSIS
|
||||||
|
|
||||||
|
stris
|
||||||
|
.RB [ -7bcdlu ]
|
||||||
|
.RB [ -i\ inclusions ]
|
||||||
|
.RB strings...
|
||||||
|
.\"
|
||||||
|
.SH DESCRIPTION
|
||||||
|
|
||||||
|
Test each character in any number of string arguments, ensuring each meets any
|
||||||
|
of the parameters specified by program options.
|
||||||
|
.\"
|
||||||
|
.SH OPTIONS
|
||||||
|
|
||||||
|
.IP \fB-7\fP
|
||||||
|
Tests if the character encoding is ASCII.
|
||||||
|
.IP \fB-b\fP
|
||||||
|
Tests if characters are whitespace.
|
||||||
|
.IP \fB-c\fP
|
||||||
|
Tests if characters are control characters.
|
||||||
|
.IP \fB-d\fP
|
||||||
|
Tests if characters are numeric.
|
||||||
|
.IP \fB-i\fP \fIinclusions...\fP
|
||||||
|
In addition to specified options, also permits characters in
|
||||||
|
.IR inclusions .
|
||||||
|
.IP \fB-l\fP
|
||||||
|
Tests if characters are in lower case.
|
||||||
|
.IP \fB-u\fP
|
||||||
|
Tests if characters are in upper case.
|
||||||
|
.\"
|
||||||
|
.SH DIAGNOSTICS
|
||||||
|
|
||||||
|
If no test cases pass for a character in
|
||||||
|
.IR strings ,
|
||||||
|
the program will exit unsuccessfully.
|
||||||
|
|
||||||
|
.SH CAVEATS
|
||||||
|
|
||||||
|
If no options are specified, the program will exit successfully as long as the
|
||||||
|
input
|
||||||
|
.I strings
|
||||||
|
are legibly encoded.
|
||||||
|
|
||||||
|
Neither which test failed nor which of the
|
||||||
|
.I strings
|
||||||
|
failed a test cannot be known without further invocations of the program.
|
||||||
|
|
||||||
|
Characters that can be encoded losslessly into ASCII from UTF-8 but which
|
||||||
|
are in an \(lqoverlong encoding\(rq, where the character was encoded with
|
||||||
|
unnecessary leading zeroes causing it to span multiple bytes, won\(cqt be
|
||||||
|
detected as ASCII.
|
||||||
|
.\"
|
||||||
|
.SH EXAMPLES
|
||||||
|
|
||||||
|
This is an
|
||||||
|
.BR sh (1p)
|
||||||
|
snippet which tests if an environment variable is an ASCII digit.
|
||||||
|
|
||||||
|
.RS
|
||||||
|
stris -7 "$v" && stris -d "$v" && echo ASCII digit.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
This is an
|
||||||
|
.BR sh (1p)
|
||||||
|
snippet that tests if an environment variable is a hexadecimal number.
|
||||||
|
|
||||||
|
.RS
|
||||||
|
stris -7 "$v" && stris -di ABCDEFabcdef "$v" && echo Hexadecimal number.
|
||||||
|
.RE
|
||||||
|
.\"
|
||||||
|
.SH AUTHOR
|
||||||
|
|
||||||
|
Written by DTB
|
||||||
|
.MT trinity@trinity.moe
|
||||||
|
.ME .
|
||||||
|
.\"
|
||||||
|
.SH HISTORY
|
||||||
|
|
||||||
|
This program replaces the former str(1) which took the name of a function from
|
||||||
|
.BR ctype (3p)
|
||||||
|
as its first argument and checked the following strings against it;
|
||||||
|
.BR str (1)
|
||||||
|
exited unsuccessfully when it encountered any non-ASCII characters and could
|
||||||
|
only have one parameter specified.
|
||||||
|
.\"
|
||||||
|
.SH COPYRIGHT
|
||||||
|
|
||||||
|
Copyright \(co 2023\(en2024 DTB. License AGPLv3+: GNU AGPL version 3 or later
|
||||||
|
<https://gnu.org/licenses/gpl.html>.
|
||||||
|
.\"
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ascii (7),
|
||||||
|
.BR ctype (3p),
|
||||||
|
.BR strcmp (1)
|
||||||
31
src/dj.c
31
src/dj.c
@@ -108,8 +108,10 @@ Io_write(struct Io *io) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
oserr(char *e, int n) {
|
oserr(char *e, int n) { /* program_name: [failing component:] error */
|
||||||
(void)fprintf(stderr, "%s: %s: %s\n", program_name, e, strerror(n));
|
(void)fprintf(stderr, "%s: ", program_name);
|
||||||
|
if (e != NULL) { (void)fprintf(stderr, "%s: ", e); }
|
||||||
|
(void)fprintf(stderr, "%s\n", strerror(n));
|
||||||
|
|
||||||
return EX_OSERR;
|
return EX_OSERR;
|
||||||
}
|
}
|
||||||
@@ -168,12 +170,6 @@ usage(char *argv0) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
#ifdef __OpenBSD__
|
|
||||||
if (pledge("cpath rpath stdio unveil wpath", NULL) == -1) {
|
|
||||||
return oserr("pledge", errno);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int align; /* low 8b used, negative if no alignment is being done */
|
int align; /* low 8b used, negative if no alignment is being done */
|
||||||
int count; /* -1 if dj(1) runs until no more reads are possible */
|
int count; /* -1 if dj(1) runs until no more reads are possible */
|
||||||
char *fmt; /* set to fmt_asv (default) or fmt_human (-H) */
|
char *fmt; /* set to fmt_asv (default) or fmt_human (-H) */
|
||||||
@@ -181,6 +177,12 @@ int main(int argc, char *argv[]) {
|
|||||||
bool retry; /* false if exits on partial reads or writes */
|
bool retry; /* false if exits on partial reads or writes */
|
||||||
struct Io io[2 /* { in, out } */];
|
struct Io io[2 /* { in, out } */];
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
if (pledge("cpath rpath stdio unveil wpath", NULL) == -1) {
|
||||||
|
return oserr(NULL, errno);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Set defaults. */
|
/* Set defaults. */
|
||||||
align = -1;
|
align = -1;
|
||||||
count = -1;
|
count = -1;
|
||||||
@@ -215,14 +217,10 @@ int main(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
char *perms = "wc";
|
if (unveil(optarg, i == 0 ? "r" : "wc") == -1) {
|
||||||
|
return oserr(NULL, errno);
|
||||||
/* modify perms in-place to read-only */
|
|
||||||
if (i == 0) { perms = "r"; }
|
|
||||||
|
|
||||||
if (unveil(optarg, perms) == -1) {
|
|
||||||
return oserr("unveil", errno);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -265,8 +263,9 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
if (unveil(NULL, NULL) == -1) { return oserr("unveil", errno); }
|
if (unveil(NULL, NULL) == -1) { return oserr(NULL, errno); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(io->fd != STDIN_FILENO || io->fl == read_flags);
|
assert(io->fd != STDIN_FILENO || io->fl == read_flags);
|
||||||
|
|||||||
14
src/hru.rs
14
src/hru.rs
@@ -29,6 +29,10 @@ extern crate sysexits;
|
|||||||
use strerror::StrError;
|
use strerror::StrError;
|
||||||
use sysexits::{ EX_DATAERR, EX_IOERR, EX_SOFTWARE, EX_USAGE };
|
use sysexits::{ EX_DATAERR, EX_IOERR, EX_SOFTWARE, EX_USAGE };
|
||||||
|
|
||||||
|
#[cfg(target_os="openbsd")] use sysexits::EX_OSERR;
|
||||||
|
#[cfg(target_os="openbsd")] extern crate openbsd;
|
||||||
|
#[cfg(target_os="openbsd")] use openbsd::{ Promises, pledge };
|
||||||
|
|
||||||
/* list of SI prefixes */
|
/* list of SI prefixes */
|
||||||
const LIST: [(u32, &str); 10] = [
|
const LIST: [(u32, &str); 10] = [
|
||||||
(3, "k"), /* kilo */
|
(3, "k"), /* kilo */
|
||||||
@@ -76,10 +80,20 @@ fn convert(input: u128) -> Result<(f64, (u32, &'static str)), String> {
|
|||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
let argv = args().collect::<Vec<String>>();
|
let argv = args().collect::<Vec<String>>();
|
||||||
|
|
||||||
if let Some(_) = argv.get(1) {
|
if let Some(_) = argv.get(1) {
|
||||||
eprintln!("Usage: {}", argv[0]);
|
eprintln!("Usage: {}", argv[0]);
|
||||||
return ExitCode::from(EX_USAGE as u8);
|
return ExitCode::from(EX_USAGE as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cfg!(target_os="openbsd") {
|
||||||
|
let promises = Promises::new("stdio");
|
||||||
|
if let Err(e) = pledge(Some(promises), None) {
|
||||||
|
eprintln!("{}: {}", argv[0], e.strerror());
|
||||||
|
return ExitCode::from(EX_OSERR as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
|
|
||||||
while let Ok(_) = stdin().read_line(&mut buf) {
|
while let Ok(_) = stdin().read_line(&mut buf) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2023–2024 DTB <trinity@trinity.moe>
|
* Copyright (c) 2023–2024 DTB <trinity@trinity.moe>
|
||||||
|
* Copyright (c) 2024 Emma Tebibyte <emma@tebibyte.media>
|
||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it under
|
* This program is free software: you can redistribute it and/or modify it under
|
||||||
@@ -22,11 +23,18 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern crate getopt;
|
extern crate getopt;
|
||||||
use getopt::GetOpt;
|
|
||||||
|
|
||||||
extern crate sysexits;
|
extern crate sysexits;
|
||||||
|
|
||||||
|
use getopt::GetOpt;
|
||||||
use sysexits::EX_USAGE;
|
use sysexits::EX_USAGE;
|
||||||
|
|
||||||
|
#[cfg(target_os="openbsd")] use sysexits::EX_OSERR;
|
||||||
|
#[cfg(target_os="openbsd")] extern crate openbsd;
|
||||||
|
#[cfg(target_os="openbsd")] extern crate strerror;
|
||||||
|
#[cfg(target_os="openbsd")] use openbsd::{ Promises, pledge };
|
||||||
|
#[cfg(target_os="openbsd")] use strerror::StrError;
|
||||||
|
|
||||||
|
|
||||||
fn usage(s: &str) -> ExitCode {
|
fn usage(s: &str) -> ExitCode {
|
||||||
eprintln!("Usage: {} [-egl] integer integer...", s);
|
eprintln!("Usage: {} [-egl] integer integer...", s);
|
||||||
ExitCode::from(EX_USAGE as u8)
|
ExitCode::from(EX_USAGE as u8)
|
||||||
@@ -34,6 +42,15 @@ fn usage(s: &str) -> ExitCode {
|
|||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
let argv = args().collect::<Vec<String>>();
|
let argv = args().collect::<Vec<String>>();
|
||||||
|
|
||||||
|
if cfg!(target_os="openbsd") {
|
||||||
|
let promises = Promises::new("stdio");
|
||||||
|
if let Err(e) = pledge(Some(promises), None) {
|
||||||
|
eprintln!("{}: {}", argv[0], e.strerror());
|
||||||
|
return ExitCode::from(EX_OSERR as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut e = false; /* args can be == */
|
let mut e = false; /* args can be == */
|
||||||
let mut g = false; /* args can be > */
|
let mut g = false; /* args can be > */
|
||||||
let mut l = false; /* args can be < */
|
let mut l = false; /* args can be < */
|
||||||
@@ -46,11 +63,13 @@ fn main() -> ExitCode {
|
|||||||
Ok("e") => e = true,
|
Ok("e") => e = true,
|
||||||
Ok("g") => g = true,
|
Ok("g") => g = true,
|
||||||
Ok("l") => l = true,
|
Ok("l") => l = true,
|
||||||
_ => { return usage(&argv[0]); },
|
_ => return usage(&argv[0]),
|
||||||
}
|
}
|
||||||
optind = opt.ind();
|
optind = opt.ind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !e & !g & !l { return usage(&argv[0]); }
|
||||||
|
|
||||||
if argv.len() - optind < 2 /* see usage */ { return usage(&argv[0]); }
|
if argv.len() - optind < 2 /* see usage */ { return usage(&argv[0]); }
|
||||||
|
|
||||||
let mut prev: Option<usize> = None; /* no previous operand */
|
let mut prev: Option<usize> = None; /* no previous operand */
|
||||||
@@ -59,8 +78,8 @@ fn main() -> ExitCode {
|
|||||||
for arg in argv.iter().skip(optind) { /* iterate operands */
|
for arg in argv.iter().skip(optind) { /* iterate operands */
|
||||||
match arg.parse::<usize>() { /* parse current operand */
|
match arg.parse::<usize>() { /* parse current operand */
|
||||||
Ok(n) => currn = n,
|
Ok(n) => currn = n,
|
||||||
_ => {
|
Err(e) => {
|
||||||
eprintln!("{}: {}: Invalid integer", &argv[0], arg);
|
eprintln!("{}: {}: {}", &argv[0], arg, e);
|
||||||
return ExitCode::from(EX_USAGE as u8);
|
return ExitCode::from(EX_USAGE as u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
ffi::CString,
|
ffi::{ CString, c_char },
|
||||||
io::Error,
|
io::Error,
|
||||||
ptr::null,
|
ptr::null,
|
||||||
};
|
};
|
||||||
@@ -33,13 +33,13 @@ mod openbsd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Promises(*const i8);
|
pub struct Promises(*const c_char);
|
||||||
|
|
||||||
impl Promises {
|
impl Promises {
|
||||||
pub fn new(promises: &str) -> Self {
|
pub fn new(promises: &str) -> Self {
|
||||||
let p = CString::new(promises).unwrap();
|
let p = CString::new(promises).unwrap();
|
||||||
|
|
||||||
Promises(p.into_raw() as *const i8)
|
Promises(p.into_raw() as *const c_char)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,10 +81,10 @@ pub fn unveil(
|
|||||||
permissions: Option<UnveilPerms>,
|
permissions: Option<UnveilPerms>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let path_c = path.map(CString::new).map(Result::unwrap);
|
let path_c = path.map(CString::new).map(Result::unwrap);
|
||||||
let arg1 = path_c.map(|p| p.into_raw() as *const i8).unwrap_or(null());
|
let arg1 = path_c.map(|p| p.into_raw() as *const c_char).unwrap_or(null());
|
||||||
|
|
||||||
let arg2 = permissions
|
let arg2 = permissions
|
||||||
.map(|p| p.0.into_raw() as *const i8)
|
.map(|p| p.0.into_raw() as *const c_char)
|
||||||
.unwrap_or(null());
|
.unwrap_or(null());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
@@ -131,7 +131,10 @@ fn main() -> ExitCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{:?}", ins);
|
if ins.is_empty() && outs.is_empty() && argv.len() > optind {
|
||||||
|
eprintln!("Usage: {}", usage);
|
||||||
|
return ExitCode::from(EX_USAGE as u8);
|
||||||
|
}
|
||||||
|
|
||||||
/* use stdin if no inputs are specified */
|
/* use stdin if no inputs are specified */
|
||||||
if ins.is_empty() { ins.push("-".to_string()); }
|
if ins.is_empty() { ins.push("-".to_string()); }
|
||||||
|
|||||||
11
src/npc.c
11
src/npc.c
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
#include <stdio.h> /* fprintf(3), fputs(3), getc(3), perror(3), putc(3), stdin,
|
#include <stdio.h> /* fprintf(3), fputs(3), getc(3), perror(3), putc(3), stdin,
|
||||||
* stdout, EOF */
|
* stdout, EOF */
|
||||||
#include <sysexits.h> /* EX_IOERR, EX_OK, EX_USAGE */
|
#include <sysexits.h> /* EX_IOERR, EX_OK, EX_OSERR, EX_USAGE */
|
||||||
#include <unistd.h> /* getopt(3) */
|
#include <unistd.h> /* pledge(2), getopt(3) */
|
||||||
|
|
||||||
char *program_name = "npc";
|
char *program_name = "npc";
|
||||||
|
|
||||||
@@ -43,6 +43,13 @@ int main(int argc, char *argv[]) {
|
|||||||
char showend = 0; /* print a dollar sign before each newline */
|
char showend = 0; /* print a dollar sign before each newline */
|
||||||
char showtab = 0; /* prints tab characters in caret notation */
|
char showtab = 0; /* prints tab characters in caret notation */
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
if (pledge("stdio", NULL) == -1) {
|
||||||
|
perror(argv[0] == NULL ? program_name : argv[0]);
|
||||||
|
return EX_OSERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
program_name = argv[0];
|
program_name = argv[0];
|
||||||
|
|
||||||
|
|||||||
15
src/rpn.rs
15
src/rpn.rs
@@ -56,6 +56,12 @@ extern crate sysexits;
|
|||||||
|
|
||||||
use sysexits::EX_DATAERR;
|
use sysexits::EX_DATAERR;
|
||||||
|
|
||||||
|
#[cfg(target_os="openbsd")] use sysexits::EX_OSERR;
|
||||||
|
#[cfg(target_os="openbsd")] extern crate strerror;
|
||||||
|
#[cfg(target_os="openbsd")] extern crate openbsd;
|
||||||
|
#[cfg(target_os="openbsd")] use strerror::StrError;
|
||||||
|
#[cfg(target_os="openbsd")] use openbsd::{ Promises, pledge };
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, PartialOrd, Debug)]
|
#[derive(Clone, PartialEq, PartialOrd, Debug)]
|
||||||
/* enum CalcType is a type containing operations used in the calculator */
|
/* enum CalcType is a type containing operations used in the calculator */
|
||||||
enum CalcType {
|
enum CalcType {
|
||||||
@@ -191,6 +197,15 @@ fn round_precise(value: &f64, precision: usize) -> f64 {
|
|||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
let argv = args().collect::<Vec<String>>();
|
let argv = args().collect::<Vec<String>>();
|
||||||
|
|
||||||
|
if cfg!(target_os="openbsd") {
|
||||||
|
let promises = Promises::new("stdio");
|
||||||
|
if let Err(e) = pledge(Some(promises), None) {
|
||||||
|
eprintln!("{}: {}", argv[0], e.strerror());
|
||||||
|
return ExitCode::from(EX_OSERR as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut stack = VecDeque::new();
|
let mut stack = VecDeque::new();
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
/* Set floating-point precision for correcting rounding errors based on
|
/* Set floating-point precision for correcting rounding errors based on
|
||||||
|
|||||||
34
src/scrut.c
34
src/scrut.c
@@ -17,18 +17,21 @@
|
|||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h> /* assert(3) */
|
||||||
#include <stdio.h> /* fprintf(3), stderr, NULL */
|
#include <stdio.h> /* fprintf(3), stderr, NULL */
|
||||||
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
|
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
|
||||||
#include <string.h> /* memset(3), strchr(3) */
|
#include <string.h> /* memset(3), strchr(3) */
|
||||||
#include <sysexits.h> /* EX_USAGE */
|
#include <sysexits.h> /* EX_OSERR, EX_USAGE */
|
||||||
#include <unistd.h> /* access(3), getopt(3), F_OK, R_OK, W_OK, X_OK */
|
#include <unistd.h> /* access(3), getopt(3), pledge(2), unveil(2), F_OK, R_OK,
|
||||||
|
* W_OK, X_OK */
|
||||||
#include <sys/stat.h> /* lstat(3), stat struct, S_ISBLK, S_ISCHR, S_ISDIR,
|
#include <sys/stat.h> /* lstat(3), stat struct, S_ISBLK, S_ISCHR, S_ISDIR,
|
||||||
* S_ISFIFO, S_ISGID, S_ISREG, S_ISLNK, S_ISSOCK,
|
* S_ISFIFO, S_ISGID, S_ISREG, S_ISLNK, S_ISSOCK,
|
||||||
* S_ISUID, S_ISVTX */
|
* S_ISUID, S_ISVTX */
|
||||||
|
|
||||||
char *program_name = "scrut";
|
char *program_name = "scrut";
|
||||||
#define OPTS "bcdefgkprsuwxLS"
|
#define OPTS "bcdefgkprsuwxLS"
|
||||||
static char *opts = OPTS;
|
/* this is an array so main:sel's size can be known at compile time */
|
||||||
|
static char opts[] = OPTS;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
usage(char *argv0) {
|
usage(char *argv0) {
|
||||||
@@ -40,7 +43,16 @@ usage(char *argv0) {
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
char sel[(sizeof opts) / (sizeof *opts)];
|
char sel[(sizeof opts) / (sizeof *opts)];
|
||||||
|
|
||||||
if (argc < 2) { return usage(argv[0] == NULL ? program_name : argv[0]); }
|
program_name = argv[0] == NULL ? program_name : argv[0];
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
if (pledge("rpath stdio unveil", NULL) == -1) {
|
||||||
|
perror(program_name);
|
||||||
|
return EX_OSERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (argc < 2) { return usage(program_name); }
|
||||||
|
|
||||||
{ /* option parsing */
|
{ /* option parsing */
|
||||||
char *p;
|
char *p;
|
||||||
@@ -48,7 +60,10 @@ int main(int argc, char *argv[]) {
|
|||||||
memset(sel, '\0', sizeof sel);
|
memset(sel, '\0', sizeof sel);
|
||||||
for (int c; (c = getopt(argc, argv, opts)) != -1;) {
|
for (int c; (c = getopt(argc, argv, opts)) != -1;) {
|
||||||
if ((p = strchr(opts, c)) == NULL) { return usage(argv[0]); }
|
if ((p = strchr(opts, c)) == NULL) { return usage(argv[0]); }
|
||||||
else { sel[p - opts] = c; }
|
else {
|
||||||
|
assert(p - opts < sizeof sel / sizeof *sel); /* bounds check */
|
||||||
|
sel[p - opts] = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* straighten out selections; permute out nulls */
|
/* straighten out selections; permute out nulls */
|
||||||
@@ -63,9 +78,16 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
if (optind == argc) { return usage(argv[0]); }
|
if (optind == argc) { return usage(argv[0]); }
|
||||||
|
|
||||||
for (argv += optind ; *argv != NULL; ++argv) {
|
for (argv += optind ; *argv != NULL; argv = &argv[1]) {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
if (unveil(*argv, "r") == -1) {
|
||||||
|
perror(program_name);
|
||||||
|
return EX_OSERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if(access(*argv, F_OK) != 0 || lstat(*argv, &buf) == -1) {
|
if(access(*argv, F_OK) != 0 || lstat(*argv, &buf) == -1) {
|
||||||
return EXIT_FAILURE; /* doesn't exist or isn't stattable */
|
return EXIT_FAILURE; /* doesn't exist or isn't stattable */
|
||||||
}
|
}
|
||||||
|
|||||||
84
src/str.c
84
src/str.c
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023 DTB <trinity@trinity.moe>
|
|
||||||
* Copyright (c) 2023 Marceline Cramer <mars@tebibyte.media>
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it under
|
|
||||||
* the terms of the GNU Affero General Public License as published by the Free
|
|
||||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
|
||||||
* later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stddef.h> /* NULL */
|
|
||||||
#include <stdio.h> /* fprintf(3) */
|
|
||||||
#include <stdlib.h> /* size_t, EXIT_FAILURE */
|
|
||||||
#include <string.h> /* strcmp(3) */
|
|
||||||
#include <sysexits.h> /* EX_USAGE */
|
|
||||||
|
|
||||||
char *program_name = "str";
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
char *name;
|
|
||||||
int (*f)(int);
|
|
||||||
} ctypes[] = {
|
|
||||||
{ "isalnum", isalnum },
|
|
||||||
{ "isalpha", isalpha },
|
|
||||||
{ "isblank", isblank },
|
|
||||||
{ "iscntrl", iscntrl },
|
|
||||||
{ "isdigit", isdigit },
|
|
||||||
{ "isxdigit", isxdigit },
|
|
||||||
{ "isgraph", isgraph },
|
|
||||||
{ "islower", islower },
|
|
||||||
{ "isprint", isprint },
|
|
||||||
{ "ispunct", ispunct },
|
|
||||||
{ "isspace", isspace },
|
|
||||||
{ "isupper", isupper },
|
|
||||||
{ NULL, NULL } /* marks end */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
usage(char *argv0) {
|
|
||||||
(void)fprintf(stderr, "Usage: %s type string...\n", argv0);
|
|
||||||
|
|
||||||
return EX_USAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
size_t ctype; // selected from ctypes.h; index of ctype
|
|
||||||
int retval; // initially fail but becomes success on the first valid char
|
|
||||||
|
|
||||||
if (argc < 3) { return usage(argv[0] == NULL ? program_name : argv[0]); }
|
|
||||||
|
|
||||||
for ( /* iterate ctypes */
|
|
||||||
ctype = 0;
|
|
||||||
ctypes[ctype].f != NULL /* break at the end of ctypes */
|
|
||||||
&& strcmp(argv[1], ctypes[ctype].name) != 0; /* break at match */
|
|
||||||
++ctype
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ctypes[ctype].f == NULL) { return usage(argv[0]); }
|
|
||||||
|
|
||||||
/* iterate args */
|
|
||||||
for (argv += 2, retval = EXIT_FAILURE; *argv != NULL; ++argv) {
|
|
||||||
for (size_t i = 0; argv[0][i] != '\0'; ++i) { /* iterate arg bytes */
|
|
||||||
/* First checks if argv[0][i] is valid ASCII; ctypes(3) don't
|
|
||||||
* handle non-ASCII. This is bad. */
|
|
||||||
if(
|
|
||||||
(unsigned char)argv[0][i] < 0x80 // argv[0][i] is ASCII,
|
|
||||||
&& !ctypes[ctype].f(argv[0][i]) // so use ctypes(3)
|
|
||||||
) { return EXIT_FAILURE; }
|
|
||||||
else { retval = EXIT_SUCCESS; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
18
src/strcmp.c
18
src/strcmp.c
@@ -16,13 +16,25 @@
|
|||||||
* You should have received a copy of the GNU Affero General Public License
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
#include <stdio.h> /* fprintf(3), stderr */
|
#include <stdio.h> /* fprintf(3), perror(3), stderr */
|
||||||
#include <sysexits.h> /* EX_OK, EX_USAGE */
|
#include <sysexits.h> /* EX_OK, EX_OSERR, EX_USAGE */
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
# include <unistd.h> /* pledge(2) */
|
||||||
|
#endif
|
||||||
|
|
||||||
char *program_name = "strcmp";
|
char *program_name = "strcmp";
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
#ifdef __OpenBSD__
|
||||||
|
if (pledge("stdio", NULL) == -1) {
|
||||||
|
perror(argv[0] == NULL ? program_name : argv[0]);
|
||||||
|
|
||||||
|
return EX_OSERR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
(void)fprintf(
|
(void)fprintf(
|
||||||
|
|||||||
87
src/stris.rs
Normal file
87
src/stris.rs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023–2024 DTB <trinity@trinity.moe>
|
||||||
|
* Copyright (c) 2023 Marceline Cramer <mars@tebibyte.media>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it under
|
||||||
|
* the terms of the GNU Affero General Public License as published by the Free
|
||||||
|
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
env::args,
|
||||||
|
process::ExitCode,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern crate getopt;
|
||||||
|
extern crate sysexits;
|
||||||
|
|
||||||
|
use getopt::GetOpt;
|
||||||
|
use sysexits::EX_USAGE;
|
||||||
|
|
||||||
|
struct Reqs {
|
||||||
|
ascii: bool, blank: bool, cntrl: bool, digit: bool, lower: bool,
|
||||||
|
upper: bool, inuse: bool, extra: String
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(s: &str) -> ExitCode {
|
||||||
|
eprintln!("Usage: {} [-7bcdlu] [-i inclusions] [strings...]", s);
|
||||||
|
ExitCode::from(EX_USAGE as u8)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> ExitCode {
|
||||||
|
let argv = args().collect::<Vec<String>>();
|
||||||
|
let mut optind = 1;
|
||||||
|
let mut reqs = Reqs {
|
||||||
|
ascii: false, blank: false, cntrl: false, digit: false, lower: false,
|
||||||
|
upper: false, inuse: false, extra: String::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Some(opt) = argv.getopt("7bcdi:lu") {
|
||||||
|
match opt.opt() {
|
||||||
|
Ok("7") => reqs.ascii = true,
|
||||||
|
Ok("b") => reqs.blank = true,
|
||||||
|
Ok("c") => reqs.cntrl = true,
|
||||||
|
Ok("d") => reqs.digit = true,
|
||||||
|
Ok("i") => reqs.extra = opt.arg().unwrap(),
|
||||||
|
Ok("l") => reqs.lower = true,
|
||||||
|
Ok("u") => reqs.upper = true,
|
||||||
|
_ => { return usage(&argv[0]); }
|
||||||
|
}
|
||||||
|
optind = opt.ind();
|
||||||
|
reqs.inuse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if argv.len() == optind { return usage(&argv[0]); }
|
||||||
|
|
||||||
|
drop(argv);
|
||||||
|
|
||||||
|
if reqs.inuse {
|
||||||
|
for arg in args().skip(optind) {
|
||||||
|
for c in arg.chars() {
|
||||||
|
if (reqs.ascii && c.is_ascii())
|
||||||
|
|| (reqs.blank && c.is_whitespace())
|
||||||
|
|| (reqs.cntrl && c.is_control())
|
||||||
|
|| (reqs.digit && c.is_numeric())
|
||||||
|
|| (reqs.lower && c.is_lowercase())
|
||||||
|
|| (reqs.upper && c.is_uppercase())
|
||||||
|
|| reqs.extra.contains(c) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return ExitCode::FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ExitCode::SUCCESS
|
||||||
|
}
|
||||||
12
src/swab.rs
12
src/swab.rs
@@ -32,6 +32,10 @@ use getopt::GetOpt;
|
|||||||
use sysexits::{ EX_IOERR, EX_OK, EX_OSERR, EX_USAGE };
|
use sysexits::{ EX_IOERR, EX_OK, EX_OSERR, EX_USAGE };
|
||||||
use strerror::StrError;
|
use strerror::StrError;
|
||||||
|
|
||||||
|
#[cfg(target_os="openbsd")] extern crate openbsd;
|
||||||
|
#[cfg(target_os="openbsd")] use openbsd::{ Promises, pledge };
|
||||||
|
|
||||||
|
|
||||||
fn oserr(argv0: &str, e: Error) -> ExitCode {
|
fn oserr(argv0: &str, e: Error) -> ExitCode {
|
||||||
eprintln!("{}: {}", argv0, e.strerror());
|
eprintln!("{}: {}", argv0, e.strerror());
|
||||||
ExitCode::from(EX_OSERR as u8)
|
ExitCode::from(EX_OSERR as u8)
|
||||||
@@ -49,6 +53,14 @@ fn usage(s: &str) -> ExitCode {
|
|||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
let argv = args().collect::<Vec<String>>();
|
let argv = args().collect::<Vec<String>>();
|
||||||
|
|
||||||
|
if cfg!(target_os="openbsd") {
|
||||||
|
let promises = Promises::new("stdio");
|
||||||
|
if let Err(e) = pledge(Some(promises), None) {
|
||||||
|
return oserr(&argv[0], e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut buf: Vec<u8> = Vec::new(); // holds the sequence getting swabbed
|
let mut buf: Vec<u8> = Vec::new(); // holds the sequence getting swabbed
|
||||||
let mut input = stdin();
|
let mut input = stdin();
|
||||||
let mut output = stdout().lock();
|
let mut output = stdout().lock();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# notice are preserved. This file is offered as-is, without any warranty.
|
# notice are preserved. This file is offered as-is, without any warranty.
|
||||||
|
|
||||||
.PHONY: intcmp_tests
|
.PHONY: intcmp_tests
|
||||||
intcmp_tests: intcmp_help intcmp_e intcmp_g intcmp_l intcmp_combined
|
intcmp_tests: intcmp_help intcmp_none intcmp_e intcmp_g intcmp_l intcmp_combined
|
||||||
|
|
||||||
.PHONY: intcmp_help
|
.PHONY: intcmp_help
|
||||||
intcmp_help: $(BIN)/intcmp
|
intcmp_help: $(BIN)/intcmp
|
||||||
@@ -31,6 +31,10 @@ intcmp_help: $(BIN)/intcmp
|
|||||||
# the invocation. If this test failed, intcmp(1) would be confusing -l for -g,
|
# the invocation. If this test failed, intcmp(1) would be confusing -l for -g,
|
||||||
# so that would be a good place to start looking for bugs.
|
# so that would be a good place to start looking for bugs.
|
||||||
|
|
||||||
|
.PHONY: intcmp_none
|
||||||
|
intcmp_none: $(BIN)/intcmp
|
||||||
|
! $(BIN)/intcmp 1 2
|
||||||
|
|
||||||
.PHONY: intcmp_e
|
.PHONY: intcmp_e
|
||||||
intcmp_e: $(BIN)/intcmp
|
intcmp_e: $(BIN)/intcmp
|
||||||
$(BIN)/intcmp -e 3 3 3 # ==
|
$(BIN)/intcmp -e 3 3 3 # ==
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
# permitted in any medium without royalty provided the copyright notice and this
|
# permitted in any medium without royalty provided the copyright notice and this
|
||||||
# notice are preserved. This file is offered as-is, without any warranty.
|
# notice are preserved. This file is offered as-is, without any warranty.
|
||||||
|
|
||||||
NAME = mm
|
|
||||||
TARGET = $(NAME)_tests
|
|
||||||
BINARY = $(BIN)/$(NAME)
|
|
||||||
|
|
||||||
.PHONY: mm_tests
|
.PHONY: mm_tests
|
||||||
mm_tests: mm_args mm_help mm_stderr
|
mm_tests: mm_args mm_help mm_stderr
|
||||||
|
|
||||||
|
.PHONY: mm_none
|
||||||
|
mm_none: $(BIN)/mm
|
||||||
|
test "$$(printf 'meow\n' | $(BIN)/mm)" = meow
|
||||||
|
|
||||||
.PHONY: mm_args
|
.PHONY: mm_args
|
||||||
# mm(1) will error if positional arguments are given without -i or -o
|
# mm(1) will error if positional arguments are given without -i or -o
|
||||||
mm_args: $(BIN)/mm
|
mm_args: $(BIN)/mm
|
||||||
@@ -24,4 +24,4 @@ mm_help: $(BIN)/mm
|
|||||||
.PHONY: mm_stderr
|
.PHONY: mm_stderr
|
||||||
# check if stderr is empty upon specifying -e
|
# check if stderr is empty upon specifying -e
|
||||||
mm_stderr: $(BIN)/mm
|
mm_stderr: $(BIN)/mm
|
||||||
! test "$$(printf 'test\n' | $(BIN)/mm -e 2>&1 >/dev/null)" = "test"
|
test "$$(printf 'test\n' | $(BIN)/mm -e 2>&1 >/dev/null )" = "test"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# notice are preserved. This file is offered as-is, without any warranty.
|
# notice are preserved. This file is offered as-is, without any warranty.
|
||||||
|
|
||||||
.PHONY: rpn_tests
|
.PHONY: rpn_tests
|
||||||
rpn_tests: rpn_help rpn_add
|
rpn_tests: rpn_help rpn_add rpn_sub rpn_mul rpn_div rpn_mod rpn_flr
|
||||||
|
|
||||||
.PHONY: rpn_help
|
.PHONY: rpn_help
|
||||||
rpn_help: $(BIN)/rpn
|
rpn_help: $(BIN)/rpn
|
||||||
@@ -20,7 +20,7 @@ rpn_add: $(BIN)/rpn
|
|||||||
.PHONY: rpn_sub
|
.PHONY: rpn_sub
|
||||||
rpn_sub: $(BIN)/rpn
|
rpn_sub: $(BIN)/rpn
|
||||||
test "$$($(BIN)/rpn 23 5 -)" -eq 18
|
test "$$($(BIN)/rpn 23 5 -)" -eq 18
|
||||||
test "$$($(BIN)/rpn 0.3 0.1)" = 0.2
|
test "$$($(BIN)/rpn 0.3 0.1 -)" = 0.2
|
||||||
|
|
||||||
.PHONY: rpn_mul
|
.PHONY: rpn_mul
|
||||||
rpn_mul: $(BIN)/rpn
|
rpn_mul: $(BIN)/rpn
|
||||||
|
|||||||
@@ -7,14 +7,19 @@
|
|||||||
|
|
||||||
.PRAGMA: command_comment
|
.PRAGMA: command_comment
|
||||||
|
|
||||||
.PHONY: str_tests
|
.PHONY: stris_tests
|
||||||
str_tests: str_help str_isalpha
|
stris_tests: stris_help stris_7 stris_b
|
||||||
|
|
||||||
.PHONY: str_help
|
.PHONY: stris_help
|
||||||
str_help: $(BIN)/str
|
stris_help: $(BIN)/stris
|
||||||
! $(BIN)/str -h
|
! $(BIN)/stris -h
|
||||||
|
|
||||||
.PHONY: str_isalpha
|
.PHONY: stris_7
|
||||||
str_isalpha: $(BIN)/str
|
stris_7: $(BIN)/stris
|
||||||
$(BIN)/str isalpha c
|
$(BIN)/stris -7 !1Aa' '
|
||||||
! $(BIN)/str isalpha 3
|
! $(BIN)/stris -7 今日は
|
||||||
|
|
||||||
|
.PHONY: stris_b
|
||||||
|
stris_b: $(BIN)/stris
|
||||||
|
$(BIN)/stris -b "$(printf ' \t\v\r\n')"
|
||||||
|
! $(BIN)/stris -b !1Aa
|
||||||
Reference in New Issue
Block a user