commit 9af0cd2a34a261e50b40439abed2d6abefe8f726
parent ae7c43183148c8699e9357076c5d02ef6db4ef2b
Author: Byron Torres <b@torresjrjr.com>
Date: Wed, 24 Nov 2021 17:54:24 +0000
handle files
Diffstat:
M | dc.ha | | | 61 | +++++++++++++++++++++++++++++++++++++++++-------------------- |
1 file changed, 41 insertions(+), 20 deletions(-)
diff --git a/dc.ha b/dc.ha
@@ -2,6 +2,7 @@ use ascii;
use bufio;
use encoding::utf8;
use fmt;
+use fs;
use getopt;
use io;
use math;
@@ -14,29 +15,41 @@ let S: []f64 = [];
export fn main() void = {
const help: [_]getopt::help = [
"desk calculator",
- "[file]",
+ "[file ...]",
];
const cmd = getopt::parse(os::args, help...);
defer getopt::finish(&cmd);
- if (len(cmd.args) > 1) {
- usage_exit(help);
- };
+ static const buf: [1]u8 = [0...];
- let filename: (str | void) = if (len(cmd.args) == 1)
- switch (cmd.args[0]) {
+ for (let i = 0z; i < len(cmd.args); i += 1) {
+ const filename = switch (cmd.args[i]) {
case "-" =>
fmt::fatal("dc: invalid filename '-'");
case "" =>
fmt::fatal("dc: invalid filename ''");
case =>
- yield cmd.args[0];
- }
- else
- void;
+ yield cmd.args[i];
+ };
+
+ const file = match (os::open(filename)) {
+ case f: io::file =>
+ yield f;
+ case err: fs::error =>
+ fmt::fatal("dc: {} '{}'", fs::strerror(err), filename);
+ };
+ defer io::close(file);
+
+ const in = bufio::buffered(file, buf, []);
+ dc(in);
+ };
+
+ dc(os::stdin);
+};
+fn dc(in: io::handle) void = {
for (true) {
- const r = match (bufio::scanrune(os::stdin)) {
+ const r = match (bufio::scanrune(in)) {
case utf8::invalid =>
fmt::fatal("dc: invalid utf8 input");
case io::error =>
@@ -52,13 +65,13 @@ export fn main() void = {
};
if (ascii::isdigit(r)) {
- bufio::unreadrune(os::stdin, r);
- push(scan_number());
+ bufio::unreadrune(in, r);
+ push(scan_number(in));
continue;
};
if (r == '_') {
- push(-scan_number());
+ push(-scan_number(in));
continue;
};
@@ -69,13 +82,13 @@ export fn main() void = {
// printing
case 'p' =>
if (len(S) == 0) {
- fmt::errorln("dc: stack has no elements")?;
+ fmt::errorln("dc: stack empty")?;
continue;
};
fmt::println(peek())?;
case 'n' =>
if (len(S) == 0) {
- fmt::errorln("dc: stack has no elements")?;
+ fmt::errorln("dc: stack empty")?;
continue;
};
fmt::println(pop())?;
@@ -87,8 +100,16 @@ export fn main() void = {
case 'c' =>
clear();
case 'd' =>
+ if (len(S) == 0) {
+ fmt::errorln("dc: stack empty")?;
+ continue;
+ };
push(peek());
case 'r' =>
+ if (len(S) < 2) {
+ fmt::errorln("dc: stack has too few elements")?;
+ continue;
+ };
const b = pop();
const a = pop();
push(b);
@@ -102,7 +123,7 @@ export fn main() void = {
const a = S[i];
delete(S[i]);
append(S, a);
- } else if (n < 1) {
+ } else if (n < -1) {
const l = len(S): int;
const n = if (-n < l) -n else l;
const i = l - n;
@@ -169,12 +190,12 @@ export fn main() void = {
os::exit(1);
};
-fn scan_number() f64 = {
+fn scan_number(in: io::handle) f64 = {
let num: []u8 = [];
defer free(num);
let seen_decimal = false;
for (true) {
- const r = match (bufio::scanrune(os::stdin)) {
+ const r = match (bufio::scanrune(in)) {
case utf8::invalid =>
fmt::fatal("dc: invalid utf8 input");
case io::error =>
@@ -191,7 +212,7 @@ fn scan_number() f64 = {
seen_decimal = true;
};
} else {
- bufio::unreadrune(os::stdin, r);
+ bufio::unreadrune(in, r);
match (strconv::stof64(strings::fromutf8(num))) {
case (strconv::invalid | strconv::overflow) =>
abort("dc: invalid numerical input");