summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzachir <zachir@librem.one>2024-03-06 23:13:21 -0600
committerzachir <zachir@librem.one>2024-03-06 23:13:21 -0600
commit96ce2a7d932a5ea9974fc085abedecd375447e38 (patch)
treeb236b5601fd5bdc10278ff2a992ed508939ccbf6
Initial commit
Adds in zeven version 1.0.0
-rw-r--r--LICENSE19
-rw-r--r--Makefile4
-rw-r--r--build.zig70
-rw-r--r--src/main.zig149
4 files changed, 242 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e38857d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2024 Zachary Smith
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..01e4dfd
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,4 @@
+ZIG_OPTS := -Doptimize=ReleaseSmall
+
+all: src/main.zig
+ zig build ${ZIG_OPTS}
diff --git a/build.zig b/build.zig
new file mode 100644
index 0000000..7d73be1
--- /dev/null
+++ b/build.zig
@@ -0,0 +1,70 @@
+const std = @import("std");
+
+// Although this function looks imperative, note that its job is to
+// declaratively construct a build graph that will be executed by an external
+// runner.
+pub fn build(b: *std.Build) void {
+ // Standard target options allows the person running `zig build` to choose
+ // what target to build for. Here we do not override the defaults, which
+ // means any target is allowed, and the default is native. Other options
+ // for restricting supported target set are available.
+ const target = b.standardTargetOptions(.{});
+
+ // Standard optimization options allow the person running `zig build` to select
+ // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
+ // set a preferred release mode, allowing the user to decide how to optimize.
+ const optimize = b.standardOptimizeOption(.{});
+
+ const exe = b.addExecutable(.{
+ .name = "zeven",
+ // In this case the main source file is merely a path, however, in more
+ // complicated build scripts, this could be a generated file.
+ .root_source_file = .{ .path = "src/main.zig" },
+ .target = target,
+ .optimize = optimize,
+ });
+
+ // This declares intent for the executable to be installed into the
+ // standard location when the user invokes the "install" step (the default
+ // step when running `zig build`).
+ b.installArtifact(exe);
+
+ // This *creates* a Run step in the build graph, to be executed when another
+ // step is evaluated that depends on it. The next line below will establish
+ // such a dependency.
+ const run_cmd = b.addRunArtifact(exe);
+
+ // By making the run step depend on the install step, it will be run from the
+ // installation directory rather than directly from within the cache directory.
+ // This is not necessary, however, if the application depends on other installed
+ // files, this ensures they will be present and in the expected location.
+ run_cmd.step.dependOn(b.getInstallStep());
+
+ // This allows the user to pass arguments to the application in the build
+ // command itself, like this: `zig build run -- arg1 arg2 etc`
+ if (b.args) |args| {
+ run_cmd.addArgs(args);
+ }
+
+ // This creates a build step. It will be visible in the `zig build --help` menu,
+ // and can be selected like this: `zig build run`
+ // This will evaluate the `run` step rather than the default, which is "install".
+ const run_step = b.step("run", "Run the app");
+ run_step.dependOn(&run_cmd.step);
+
+ // Creates a step for unit testing. This only builds the test executable
+ // but does not run it.
+ const unit_tests = b.addTest(.{
+ .root_source_file = .{ .path = "src/main.zig" },
+ .target = target,
+ .optimize = optimize,
+ });
+
+ const run_unit_tests = b.addRunArtifact(unit_tests);
+
+ // Similar to creating the run step earlier, this exposes a `test` step to
+ // the `zig build --help` menu, providing a way for the user to request
+ // running the unit tests.
+ const test_step = b.step("test", "Run unit tests");
+ test_step.dependOn(&run_unit_tests.step);
+}
diff --git a/src/main.zig b/src/main.zig
new file mode 100644
index 0000000..e987bb0
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,149 @@
+const std = @import("std");
+const argsWithAllocator = std.process.argsWithAllocator;
+const eql = std.mem.eql;
+const expect = std.testing.expect;
+const parseInt = std.fmt.parseInt;
+const print = std.debug.print;
+const GeneralPurposeAllocator = std.heap.GeneralPurposeAllocator;
+
+/// There are 4 args: help, version, copyright, and quiet
+/// ArgType also contains longarg, which is how zeven checks if the arg
+/// will be --
+const ArgType = enum {
+ help,
+ version,
+ copyright,
+ quiet,
+ longarg,
+ badarg,
+};
+
+const VERSION = "1.0.0";
+const LICENSE = "MIT";
+
+test "@rem(-2, 2) == 0" {
+ try expect(@rem(-2, 2) == 0);
+}
+
+test "parseInt(i32, \"-2\", 10) == -2" {
+ var test_int = try parseInt(i32, "-2", 10);
+
+ try expect(test_int == -2);
+}
+
+test "parseInt(i32, \"\", 10) != 0" {
+ var test_int = try parseInt(i32, "-2", 10);
+ try expect(test_int != 0);
+}
+
+pub fn main() anyerror!u8 {
+ // This is an iterator for the provided args
+ var gpa = GeneralPurposeAllocator(.{}){};
+ const allocator = gpa.allocator();
+ defer _ = gpa.deinit();
+ var arg_it = try argsWithAllocator(allocator);
+ defer arg_it.deinit();
+ var f_arg: ?ArgType = null;
+ var f_int: i32 = undefined;
+ // This is whether or not to print the results
+ var quiet: bool = false;
+ // This is to check if a value has been provided
+ var value: bool = false;
+ // This skips the name of the binary
+ _ = arg_it.next();
+ while (arg_it.next()) |arg| {
+ f_arg = null;
+ if (arg[0] == '-') { // It's an arg!
+ f_arg = switch (arg[1]) {
+ 'h' => ArgType.help,
+ 'v' => ArgType.version,
+ 'c' => ArgType.copyright,
+ 'q' => ArgType.quiet,
+ '-' => ArgType.longarg,
+ '0'...'9' => null,
+ else => ArgType.badarg,
+ };
+ }
+ if (f_arg) |usearg| {
+ var realarg = usearg;
+ if (usearg == ArgType.longarg) {
+ if (eql(u8, arg, "--help")) {
+ realarg = ArgType.help;
+ } else if (eql(u8, arg, "--copyright")) {
+ realarg = ArgType.copyright;
+ } else if (eql(u8, arg, "--version")) {
+ realarg = ArgType.version;
+ } else if (eql(u8, arg, "--quiet")) {
+ realarg = ArgType.quiet;
+ } else {
+ realarg = ArgType.badarg;
+ }
+ }
+ _ = switch (realarg) {
+ ArgType.quiet => {
+ quiet = true;
+ continue;
+ },
+ ArgType.help => {
+ return print_arg(0);
+ },
+ ArgType.copyright => {
+ return print_arg(1);
+ },
+ ArgType.version => {
+ return print_arg(2);
+ },
+ else => {
+ return print_arg(255);
+ },
+ };
+ } else { // Not an arg!
+ value = true;
+ f_int = parseInt(i32, arg, 10) catch |err| return err;
+ }
+ }
+ if (value) {
+ if (@rem(f_int, 2) == 0) {
+ if (!quiet) {
+ print("even\n", .{});
+ }
+ return 0;
+ } else {
+ if (!quiet) {
+ print("odd\n", .{});
+ }
+ return 1;
+ }
+ } else {
+ print("No value was provided!\n", .{});
+ }
+ return 1;
+}
+
+pub fn print_arg(err: u8) !u8 {
+ return switch (err) {
+ 0 => {
+ print("zeven: a simple binary to check if a number ", .{});
+ print("is even or odd\n", .{});
+ print("\tzeven [-cvh]\n", .{});
+ print("\tzeven [--help]\n", .{});
+ print("\tzeven [--copyright]\n", .{});
+ print("\tzeven [--version]\n", .{});
+ print("\tzeven [-q] [--quiet] X\n", .{});
+ return 0;
+ },
+ 1 => {
+ print("zeven is Free software under the {s} license.\n", .{LICENSE});
+ print("zeven copyright (c) Zachary Smith 2024\n", .{});
+ return 0;
+ },
+ 2 => {
+ print("zeven version {s}\n", .{VERSION});
+ return 0;
+ },
+ else => {
+ print("Error!\n", .{});
+ return 1;
+ },
+ };
+}