Skip to content

Commit

Permalink
Environment: Add environment variable abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
ehaas committed Aug 3, 2023
1 parent c3cd556 commit db10f53
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/Builtins.zig
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ pub fn getOrCreate(b: *Builtins, comp: *Compilation, name: []const u8, type_aren
}

test "All builtins" {
var comp = Compilation.init(std.testing.allocator);
var comp = Compilation.init(std.testing.allocator, .{});
defer comp.deinit();
_ = try comp.generateBuiltinMacros();
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
Expand All @@ -316,7 +316,7 @@ test "All builtins" {
test "Allocation failures" {
const Test = struct {
fn testOne(allocator: std.mem.Allocator) !void {
var comp = Compilation.init(allocator);
var comp = Compilation.init(allocator, .{});
defer comp.deinit();
_ = try comp.generateBuiltinMacros();
var arena = std.heap.ArenaAllocator.init(comp.gpa);
Expand Down
13 changes: 8 additions & 5 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const Allocator = mem.Allocator;
const EpochSeconds = std.time.epoch.EpochSeconds;
const Builtins = @import("Builtins.zig");
const Diagnostics = @import("Diagnostics.zig");
const Environment = @import("Environment.zig");
const LangOpts = @import("LangOpts.zig");
const Source = @import("Source.zig");
const Tokenizer = @import("Tokenizer.zig");
Expand All @@ -26,6 +27,7 @@ pub const Error = error{
pub const bit_int_max_bits = 128;

gpa: Allocator,
environment: Environment,
sources: std.StringArrayHashMap(Source),
diag: Diagnostics,
include_dirs: std.ArrayList([]const u8),
Expand Down Expand Up @@ -61,9 +63,10 @@ types: struct {
invalid_utf8_locs: std.AutoHashMapUnmanaged(Source.Id, u32) = .{},
string_interner: StringInterner = .{},

pub fn init(gpa: Allocator) Compilation {
pub fn init(gpa: Allocator, environment: Environment) Compilation {
return .{
.gpa = gpa,
.environment = environment,
.sources = std.StringArrayHashMap(Source).init(gpa),
.diag = Diagnostics.init(gpa),
.include_dirs = std.ArrayList([]const u8).init(gpa),
Expand Down Expand Up @@ -1293,7 +1296,7 @@ pub const renderErrors = Diagnostics.render;
test "addSourceFromReader" {
const Test = struct {
fn addSourceFromReader(str: []const u8, expected: []const u8, warning_count: u32, splices: []const u32) !void {
var comp = Compilation.init(std.testing.allocator);
var comp = Compilation.init(std.testing.allocator, .{});
defer comp.deinit();

var buf_reader = std.io.fixedBufferStream(str);
Expand All @@ -1305,7 +1308,7 @@ test "addSourceFromReader" {
}

fn withAllocationFailures(allocator: std.mem.Allocator) !void {
var comp = Compilation.init(allocator);
var comp = Compilation.init(allocator, .{});
defer comp.deinit();

_ = try comp.addSourceFromBuffer("path", "spliced\\\nbuffer\n");
Expand Down Expand Up @@ -1347,7 +1350,7 @@ test "addSourceFromReader - exhaustive check for carriage return elimination" {
const alen = alphabet.len;
var buf: [alphabet.len]u8 = [1]u8{alphabet[0]} ** alen;

var comp = Compilation.init(std.testing.allocator);
var comp = Compilation.init(std.testing.allocator, .{});
defer comp.deinit();

var source_count: u32 = 0;
Expand Down Expand Up @@ -1375,7 +1378,7 @@ test "ignore BOM at beginning of file" {

const Test = struct {
fn run(buf: []const u8, input_type: enum { valid_utf8, invalid_utf8 }) !void {
var comp = Compilation.init(std.testing.allocator);
var comp = Compilation.init(std.testing.allocator, .{});
defer comp.deinit();

var buf_reader = std.io.fixedBufferStream(buf);
Expand Down
73 changes: 73 additions & 0 deletions src/Environment.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Environment variables used by aro
//! Aro internals should avoid calling `getenv` because it will not always be available
//! e.g. if using aro as a library on linux without linking libc
//! See https://github.com/ziglang/zig/issues/4524
//! Instead, the environment variables should be loaded by the driver and passed to the compilation

const std = @import("std");
const enums = std.enums;

const Environment = @This();

pub const Name = enum {
SOURCE_DATE_EPOCH,
};

const FieldType = ?[]const u8;
const default_value: FieldType = null;

const Variables = [enums.directEnumArrayLen(Name, 0)]?[]const u8;
const FieldStruct = enums.EnumFieldStruct(Name, FieldType, default_value);
const Default: Variables = enums.directEnumArrayDefault(Name, FieldType, default_value, 0, .{});

variables: Variables = Default,

/// See tests for usage
pub fn init(variables: FieldStruct) Environment {
return Environment{
.variables = enums.directEnumArrayDefault(Name, FieldType, default_value, 0, variables),
};
}

/// Load the environment variables using the std.process API
/// `self` owns the strings that are loaded, and deinitFromProcess should be called for cleanup
pub fn initFromProcess(allocator: std.mem.Allocator) !Environment {
var self: Environment = .{};
var env_map = try std.process.getEnvMap(allocator);
defer env_map.deinit();
errdefer self.deinitFromProcess(allocator);

for (enums.values(Name)) |name| {
const val = env_map.get(@tagName(name)) orelse continue;
self.set(name, try allocator.dupe(u8, val));
}
return self;
}

/// deinit function that should be called if `initFromProcess` was used
pub fn deinitFromProcess(self: *const Environment, allocator: std.mem.Allocator) void {
for (self.variables) |variable| {
allocator.free(variable orelse continue);
}
}

pub fn set(self: *Environment, name: Name, val: ?[]const u8) void {
self.variables[@intFromEnum(name)] = val;
}

pub fn get(self: *const Environment, name: Name) ?[]const u8 {
return self.variables[@intFromEnum(name)];
}

test Environment {
var env1 = Environment.init(.{
.SOURCE_DATE_EPOCH = "123",
});
try std.testing.expectEqualStrings("123", env1.get(.SOURCE_DATE_EPOCH).?);

var env2 = Environment.init(.{});
try std.testing.expectEqual(default_value, env2.get(.SOURCE_DATE_EPOCH));

var env3: Environment = .{};
try std.testing.expectEqual(default_value, env3.get(.SOURCE_DATE_EPOCH));
}
6 changes: 3 additions & 3 deletions src/Preprocessor.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2517,7 +2517,7 @@ test "Preserve pragma tokens sometimes" {
var buf = std.ArrayList(u8).init(allocator);
defer buf.deinit();

var comp = Compilation.init(allocator);
var comp = Compilation.init(allocator, .{});
defer comp.deinit();

try comp.addDefaultPragmaHandlers();
Expand Down Expand Up @@ -2575,7 +2575,7 @@ test "destringify" {
try std.testing.expectEqualStrings(destringified, pp.char_buf.items);
}
};
var comp = Compilation.init(allocator);
var comp = Compilation.init(allocator, .{});
defer comp.deinit();
var pp = Preprocessor.init(&comp);
defer pp.deinit();
Expand Down Expand Up @@ -2633,7 +2633,7 @@ test "Include guards" {
}

fn testIncludeGuard(allocator: std.mem.Allocator, comptime template: []const u8, tok_id: RawToken.Id, expected_guards: u32) !void {
var comp = Compilation.init(allocator);
var comp = Compilation.init(allocator, .{});
defer comp.deinit();
var pp = Preprocessor.init(&comp);
defer pp.deinit();
Expand Down
2 changes: 1 addition & 1 deletion src/Tokenizer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2095,7 +2095,7 @@ test "C23 keywords" {
}

fn expectTokensExtra(contents: []const u8, expected_tokens: []const Token.Id, standard: ?LangOpts.Standard) !void {
var comp = Compilation.init(std.testing.allocator);
var comp = Compilation.init(std.testing.allocator, .{});
defer comp.deinit();
if (standard) |provided| {
comp.langopts.standard = provided;
Expand Down
4 changes: 2 additions & 2 deletions src/Value.zig
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ test "minUnsignedBits" {
}
};

var comp = Compilation.init(std.testing.allocator);
var comp = Compilation.init(std.testing.allocator, .{});
defer comp.deinit();
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();

Expand Down Expand Up @@ -127,7 +127,7 @@ test "minSignedBits" {
}
};

var comp = Compilation.init(std.testing.allocator);
var comp = Compilation.init(std.testing.allocator, .{});
defer comp.deinit();
comp.target = (try std.zig.CrossTarget.parse(.{ .arch_os_abi = "x86_64-linux-gnu" })).toTarget();

Expand Down
11 changes: 10 additions & 1 deletion src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Allocator = mem.Allocator;
const process = std.process;
const Compilation = @import("Compilation.zig");
const Driver = @import("Driver.zig");
const Environment = @import("Environment.zig");
const target_util = @import("target.zig");

var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
Expand All @@ -29,7 +30,14 @@ pub fn main() u8 {
return 1;
};

var comp = Compilation.init(gpa);
const environment = Environment.initFromProcess(gpa) catch {
std.debug.print("out of memory\n", .{});
if (fast_exit) std.process.exit(1);
return 1;
};
defer environment.deinitFromProcess(gpa);

var comp = Compilation.init(gpa, environment);
defer comp.deinit();

comp.addDefaultPragmaHandlers() catch |er| switch (er) {
Expand Down Expand Up @@ -70,6 +78,7 @@ test {
_ = @import("Codegen_legacy.zig");
_ = @import("Compilation.zig");
_ = @import("Diagnostics.zig");
_ = @import("Environment.zig");
_ = @import("InitList.zig");
_ = @import("LangOpts.zig");
_ = @import("Parser.zig");
Expand Down
2 changes: 1 addition & 1 deletion test/record_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ fn runTestCases(allocator: std.mem.Allocator, wg: *std.Thread.WaitGroup, test_ca
fn singleRun(alloc: std.mem.Allocator, test_case: TestCase, stats: *Stats) !void {
const path = test_case.path;

var comp = aro.Compilation.init(alloc);
var comp = aro.Compilation.init(alloc, .{});
defer comp.deinit();

try comp.addDefaultPragmaHandlers();
Expand Down
4 changes: 2 additions & 2 deletions test/runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn addCommandLineArgs(comp: *aro.Compilation, file: aro.Source, macro_buf: anyty
}

fn testOne(allocator: std.mem.Allocator, path: []const u8) !void {
var comp = aro.Compilation.init(allocator);
var comp = aro.Compilation.init(allocator, .{});
defer comp.deinit();

try comp.addDefaultPragmaHandlers();
Expand Down Expand Up @@ -130,7 +130,7 @@ pub fn main() !void {
const root_node = progress.start("Test", cases.items.len);

// prepare compiler
var initial_comp = aro.Compilation.init(gpa);
var initial_comp = aro.Compilation.init(gpa, .{});
defer initial_comp.deinit();

const cases_include_dir = try std.fs.path.join(gpa, &.{ args[1], "include" });
Expand Down

0 comments on commit db10f53

Please sign in to comment.