authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-20 23:06:04-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-20 23:06:04-04:00
logedea7a46e5484e30c338699207c8f4b4d8370c97
treeaf5d6b5650fe48c56d22a38e54db74e3871c98a8
parent5229f6ec68708c3e66393a50ad9f9032ee7f4257
parentfaf783e5959a09fb2a1680f8bb7558db96dcbed9

Merge branch 'DrDeano-master'

closes #5648

9 files changed, 200 insertions(+), 132 deletions(-)

lib/std/array_list.zig+1-1
......@@ -162,7 +162,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
162162 mem.copy(T, self.items[oldlen..], items);
163163 }
164164
165 pub usingnamespace if (T != u8) struct { } else struct {
165 pub usingnamespace if (T != u8) struct {} else struct {
166166 pub const Writer = std.io.Writer(*Self, error{OutOfMemory}, appendWrite);
167167
168168 /// Initializes a Writer which will append to the list.
lib/std/c/tokenizer.zig+50-50
......@@ -278,62 +278,62 @@ pub const Token = struct {
278278
279279 // TODO extensions
280280 pub const keywords = std.ComptimeStringMap(Id, .{
281 .{"auto", .Keyword_auto},
282 .{"break", .Keyword_break},
283 .{"case", .Keyword_case},
284 .{"char", .Keyword_char},
285 .{"const", .Keyword_const},
286 .{"continue", .Keyword_continue},
287 .{"default", .Keyword_default},
288 .{"do", .Keyword_do},
289 .{"double", .Keyword_double},
290 .{"else", .Keyword_else},
291 .{"enum", .Keyword_enum},
292 .{"extern", .Keyword_extern},
293 .{"float", .Keyword_float},
294 .{"for", .Keyword_for},
295 .{"goto", .Keyword_goto},
296 .{"if", .Keyword_if},
297 .{"int", .Keyword_int},
298 .{"long", .Keyword_long},
299 .{"register", .Keyword_register},
300 .{"return", .Keyword_return},
301 .{"short", .Keyword_short},
302 .{"signed", .Keyword_signed},
303 .{"sizeof", .Keyword_sizeof},
304 .{"static", .Keyword_static},
305 .{"struct", .Keyword_struct},
306 .{"switch", .Keyword_switch},
307 .{"typedef", .Keyword_typedef},
308 .{"union", .Keyword_union},
309 .{"unsigned", .Keyword_unsigned},
310 .{"void", .Keyword_void},
311 .{"volatile", .Keyword_volatile},
312 .{"while", .Keyword_while},
281 .{ "auto", .Keyword_auto },
282 .{ "break", .Keyword_break },
283 .{ "case", .Keyword_case },
284 .{ "char", .Keyword_char },
285 .{ "const", .Keyword_const },
286 .{ "continue", .Keyword_continue },
287 .{ "default", .Keyword_default },
288 .{ "do", .Keyword_do },
289 .{ "double", .Keyword_double },
290 .{ "else", .Keyword_else },
291 .{ "enum", .Keyword_enum },
292 .{ "extern", .Keyword_extern },
293 .{ "float", .Keyword_float },
294 .{ "for", .Keyword_for },
295 .{ "goto", .Keyword_goto },
296 .{ "if", .Keyword_if },
297 .{ "int", .Keyword_int },
298 .{ "long", .Keyword_long },
299 .{ "register", .Keyword_register },
300 .{ "return", .Keyword_return },
301 .{ "short", .Keyword_short },
302 .{ "signed", .Keyword_signed },
303 .{ "sizeof", .Keyword_sizeof },
304 .{ "static", .Keyword_static },
305 .{ "struct", .Keyword_struct },
306 .{ "switch", .Keyword_switch },
307 .{ "typedef", .Keyword_typedef },
308 .{ "union", .Keyword_union },
309 .{ "unsigned", .Keyword_unsigned },
310 .{ "void", .Keyword_void },
311 .{ "volatile", .Keyword_volatile },
312 .{ "while", .Keyword_while },
313313
314314 // ISO C99
315 .{"_Bool", .Keyword_bool},
316 .{"_Complex", .Keyword_complex},
317 .{"_Imaginary", .Keyword_imaginary},
318 .{"inline", .Keyword_inline},
319 .{"restrict", .Keyword_restrict},
315 .{ "_Bool", .Keyword_bool },
316 .{ "_Complex", .Keyword_complex },
317 .{ "_Imaginary", .Keyword_imaginary },
318 .{ "inline", .Keyword_inline },
319 .{ "restrict", .Keyword_restrict },
320320
321321 // ISO C11
322 .{"_Alignas", .Keyword_alignas},
323 .{"_Alignof", .Keyword_alignof},
324 .{"_Atomic", .Keyword_atomic},
325 .{"_Generic", .Keyword_generic},
326 .{"_Noreturn", .Keyword_noreturn},
327 .{"_Static_assert", .Keyword_static_assert},
328 .{"_Thread_local", .Keyword_thread_local},
322 .{ "_Alignas", .Keyword_alignas },
323 .{ "_Alignof", .Keyword_alignof },
324 .{ "_Atomic", .Keyword_atomic },
325 .{ "_Generic", .Keyword_generic },
326 .{ "_Noreturn", .Keyword_noreturn },
327 .{ "_Static_assert", .Keyword_static_assert },
328 .{ "_Thread_local", .Keyword_thread_local },
329329
330330 // Preprocessor directives
331 .{"include", .Keyword_include},
332 .{"define", .Keyword_define},
333 .{"ifdef", .Keyword_ifdef},
334 .{"ifndef", .Keyword_ifndef},
335 .{"error", .Keyword_error},
336 .{"pragma", .Keyword_pragma},
331 .{ "include", .Keyword_include },
332 .{ "define", .Keyword_define },
333 .{ "ifdef", .Keyword_ifdef },
334 .{ "ifndef", .Keyword_ifndef },
335 .{ "error", .Keyword_error },
336 .{ "pragma", .Keyword_pragma },
337337 });
338338
339339 // TODO do this in the preprocessor
lib/std/fs.zig+15-14
......@@ -261,17 +261,7 @@ pub const Dir = struct {
261261 name: []const u8,
262262 kind: Kind,
263263
264 pub const Kind = enum {
265 BlockDevice,
266 CharacterDevice,
267 Directory,
268 NamedPipe,
269 SymLink,
270 File,
271 UnixDomainSocket,
272 Whiteout,
273 Unknown,
274 };
264 pub const Kind = File.Kind;
275265 };
276266
277267 const IteratorError = error{AccessDenied} || os.UnexpectedError;
......@@ -1527,9 +1517,9 @@ pub const Dir = struct {
15271517
15281518 var size: ?u64 = null;
15291519 const mode = options.override_mode orelse blk: {
1530 const stat = try in_file.stat();
1531 size = stat.size;
1532 break :blk stat.mode;
1520 const st = try in_file.stat();
1521 size = st.size;
1522 break :blk st.mode;
15331523 };
15341524
15351525 var atomic_file = try dest_dir.atomicFile(dest_path, .{ .mode = mode });
......@@ -1555,6 +1545,17 @@ pub const Dir = struct {
15551545 return AtomicFile.init(dest_path, options.mode, self, false);
15561546 }
15571547 }
1548
1549 pub const Stat = File.Stat;
1550 pub const StatError = File.StatError;
1551
1552 pub fn stat(self: Dir) StatError!Stat {
1553 const file: File = .{
1554 .handle = self.fd,
1555 .capable_io_mode = .blocking,
1556 };
1557 return file.stat();
1558 }
15581559};
15591560
15601561/// Returns an handle to the current working directory. It is not opened with iteration capability.
lib/std/fs/file.zig+36-1
......@@ -29,6 +29,18 @@ pub const File = struct {
2929 pub const Mode = os.mode_t;
3030 pub const INode = os.ino_t;
3131
32 pub const Kind = enum {
33 BlockDevice,
34 CharacterDevice,
35 Directory,
36 NamedPipe,
37 SymLink,
38 File,
39 UnixDomainSocket,
40 Whiteout,
41 Unknown,
42 };
43
3244 pub const default_mode = switch (builtin.os.tag) {
3345 .windows => 0,
3446 .wasi => 0,
......@@ -219,13 +231,14 @@ pub const File = struct {
219231 /// unique across time, as some file systems may reuse an inode after its file has been deleted.
220232 /// Some systems may change the inode of a file over time.
221233 ///
222 /// On Linux, the inode _is_ structure that stores the metadata, and the inode _number_ is what
234 /// On Linux, the inode is a structure that stores the metadata, and the inode _number_ is what
223235 /// you see here: the index number of the inode.
224236 ///
225237 /// The FileIndex on Windows is similar. It is a number for a file that is unique to each filesystem.
226238 inode: INode,
227239 size: u64,
228240 mode: Mode,
241 kind: Kind,
229242
230243 /// Access time in nanoseconds, relative to UTC 1970-01-01.
231244 atime: i128,
......@@ -254,6 +267,7 @@ pub const File = struct {
254267 .inode = info.InternalInformation.IndexNumber,
255268 .size = @bitCast(u64, info.StandardInformation.EndOfFile),
256269 .mode = 0,
270 .kind = if (info.StandardInformation.Directory == 0) .File else .Directory,
257271 .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime),
258272 .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime),
259273 .ctime = windows.fromSysTime(info.BasicInformation.CreationTime),
......@@ -268,6 +282,27 @@ pub const File = struct {
268282 .inode = st.ino,
269283 .size = @bitCast(u64, st.size),
270284 .mode = st.mode,
285 .kind = switch (builtin.os.tag) {
286 .wasi => switch (st.filetype) {
287 os.FILETYPE_BLOCK_DEVICE => Kind.BlockDevice,
288 os.FILETYPE_CHARACTER_DEVICE => Kind.CharacterDevice,
289 os.FILETYPE_DIRECTORY => Kind.Directory,
290 os.FILETYPE_SYMBOLIC_LINK => Kind.SymLink,
291 os.FILETYPE_REGULAR_FILE => Kind.File,
292 os.FILETYPE_SOCKET_STREAM, os.FILETYPE_SOCKET_DGRAM => Kind.UnixDomainSocket,
293 else => Kind.Unknown,
294 },
295 else => switch (st.mode & os.S_IFMT) {
296 os.S_IFBLK => Kind.BlockDevice,
297 os.S_IFCHR => Kind.CharacterDevice,
298 os.S_IFDIR => Kind.Directory,
299 os.S_IFIFO => Kind.NamedPipe,
300 os.S_IFLNK => Kind.SymLink,
301 os.S_IFREG => Kind.File,
302 os.S_IFSOCK => Kind.UnixDomainSocket,
303 else => Kind.Unknown,
304 },
305 },
271306 .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec,
272307 .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec,
273308 .ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec,
lib/std/io/buffered_out_stream.zig+1-1
......@@ -2,4 +2,4 @@
22pub const BufferedOutStream = @import("./buffered_writer.zig").BufferedWriter;
33
44/// Deprecated: use `std.io.buffered_writer.bufferedWriter`
5pub const bufferedOutStream = @import("./buffered_writer.zig").bufferedWriter
5pub const bufferedOutStream = @import("./buffered_writer.zig").bufferedWriter;
lib/std/json.zig+2-3
......@@ -2576,8 +2576,8 @@ pub fn stringify(
25762576 },
25772577 .Array => return stringify(&value, options, out_stream),
25782578 .Vector => |info| {
2579 const array: [info.len]info.child = value;
2580 return stringify(&array, options, out_stream);
2579 const array: [info.len]info.child = value;
2580 return stringify(&array, options, out_stream);
25812581 },
25822582 else => @compileError("Unable to stringify type '" ++ @typeName(T) ++ "'"),
25832583 }
......@@ -2770,4 +2770,3 @@ test "stringify struct with custom stringifier" {
27702770test "stringify vector" {
27712771 try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{});
27722772}
2773
lib/std/os/windows/ws2_32.zig+9-9
......@@ -163,16 +163,16 @@ pub const IPPROTO_UDP = 17;
163163pub const IPPROTO_ICMPV6 = 58;
164164pub const IPPROTO_RM = 113;
165165
166pub const AI_PASSIVE = 0x00001;
167pub const AI_CANONNAME = 0x00002;
168pub const AI_NUMERICHOST = 0x00004;
169pub const AI_NUMERICSERV = 0x00008;
170pub const AI_ADDRCONFIG = 0x00400;
171pub const AI_V4MAPPED = 0x00800;
172pub const AI_NON_AUTHORITATIVE = 0x04000;
173pub const AI_SECURE = 0x08000;
166pub const AI_PASSIVE = 0x00001;
167pub const AI_CANONNAME = 0x00002;
168pub const AI_NUMERICHOST = 0x00004;
169pub const AI_NUMERICSERV = 0x00008;
170pub const AI_ADDRCONFIG = 0x00400;
171pub const AI_V4MAPPED = 0x00800;
172pub const AI_NON_AUTHORITATIVE = 0x04000;
173pub const AI_SECURE = 0x08000;
174174pub const AI_RETURN_PREFERRED_NAMES = 0x10000;
175pub const AI_DISABLE_IDN_ENCODING = 0x80000;
175pub const AI_DISABLE_IDN_ENCODING = 0x80000;
176176
177177pub const FIONBIO = -2147195266;
178178
lib/std/zig/parse.zig-1
......@@ -937,7 +937,6 @@ const Parser = struct {
937937 return node;
938938 }
939939
940
941940 while_prefix.body = try p.expectNode(parseAssignExpr, .{
942941 .ExpectedBlockOrAssignment = .{ .token = p.tok_i },
943942 });
src-self-hosted/main.zig+86-52
......@@ -546,8 +546,9 @@ const Fmt = struct {
546546 any_error: bool,
547547 color: Color,
548548 gpa: *Allocator,
549 out_buffer: std.ArrayList(u8),
549550
550 const SeenMap = std.BufSet;
551 const SeenMap = std.AutoHashMap(fs.File.INode, void);
551552};
552553
553554pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {
......@@ -641,10 +642,20 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {
641642 .seen = Fmt.SeenMap.init(gpa),
642643 .any_error = false,
643644 .color = color,
645 .out_buffer = std.ArrayList(u8).init(gpa),
644646 };
647 defer fmt.seen.deinit();
648 defer fmt.out_buffer.deinit();
645649
646650 for (input_files.span()) |file_path| {
647 try fmtPath(&fmt, file_path, check_flag);
651 // Get the real path here to avoid Windows failing on relative file paths with . or .. in them.
652 const real_path = fs.realpathAlloc(gpa, file_path) catch |err| {
653 std.debug.warn("unable to open '{}': {}\n", .{ file_path, err });
654 process.exit(1);
655 };
656 defer gpa.free(real_path);
657
658 try fmtPath(&fmt, file_path, check_flag, fs.cwd(), real_path);
648659 }
649660 if (fmt.any_error) {
650661 process.exit(1);
......@@ -670,61 +681,79 @@ const FmtError = error{
670681 ReadOnlyFileSystem,
671682 LinkQuotaExceeded,
672683 FileBusy,
684 EndOfStream,
673685} || fs.File.OpenError;
674686
675fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
676 // get the real path here to avoid Windows failing on relative file paths with . or .. in them
677 var real_path = fs.realpathAlloc(fmt.gpa, file_path) catch |err| {
678 std.debug.warn("unable to open '{}': {}\n", .{ file_path, err });
679 fmt.any_error = true;
680 return;
681 };
682 defer fmt.gpa.free(real_path);
683
684 if (fmt.seen.exists(real_path)) return;
685 try fmt.seen.put(real_path);
686
687 const source_file = fs.cwd().openFile(real_path, .{}) catch |err| switch (err) {
688 error.IsDir, error.AccessDenied => {
689 var dir = try fs.cwd().openDir(file_path, .{ .iterate = true });
690 defer dir.close();
691
692 var dir_it = dir.iterate();
693
694 while (try dir_it.next()) |entry| {
695 if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
696 const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name });
697 try fmtPath(fmt, full_path, check_mode);
698 }
699 }
700 return;
701 },
687fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void {
688 fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) {
689 error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path),
702690 else => {
703 std.debug.warn("unable to open '{}': {}\n", .{ file_path, err });
691 std.debug.warn("unable to format '{}': {}\n", .{ file_path, err });
704692 fmt.any_error = true;
705693 return;
706694 },
707695 };
696}
697
698fn fmtPathDir(
699 fmt: *Fmt,
700 file_path: []const u8,
701 check_mode: bool,
702 parent_dir: fs.Dir,
703 parent_sub_path: []const u8,
704) FmtError!void {
705 var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true });
706 defer dir.close();
707
708 const stat = try dir.stat();
709 if (try fmt.seen.put(stat.inode, {})) |_| return;
710
711 var dir_it = dir.iterate();
712 while (try dir_it.next()) |entry| {
713 const is_dir = entry.kind == .Directory;
714 if (is_dir or mem.endsWith(u8, entry.name, ".zig")) {
715 const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name });
716 defer fmt.gpa.free(full_path);
717
718 if (is_dir) {
719 try fmtPathDir(fmt, full_path, check_mode, dir, entry.name);
720 } else {
721 fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| {
722 std.debug.warn("unable to format '{}': {}\n", .{ full_path, err });
723 fmt.any_error = true;
724 return;
725 };
726 }
727 }
728 }
729}
730
731fn fmtPathFile(
732 fmt: *Fmt,
733 file_path: []const u8,
734 check_mode: bool,
735 dir: fs.Dir,
736 sub_path: []const u8,
737) FmtError!void {
738 const source_file = try dir.openFile(sub_path, .{});
708739 defer source_file.close();
709740
710 const stat = source_file.stat() catch |err| {
711 std.debug.warn("unable to stat '{}': {}\n", .{ file_path, err });
712 fmt.any_error = true;
713 return;
714 };
741 const stat = try source_file.stat();
715742
716 const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| {
717 std.debug.warn("unable to read '{}': {}\n", .{ file_path, err });
718 fmt.any_error = true;
719 return;
743 if (stat.kind == .Directory)
744 return error.IsDir;
745
746 const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| switch (err) {
747 error.ConnectionResetByPeer => unreachable,
748 error.ConnectionTimedOut => unreachable,
749 else => |e| return e,
720750 };
721751 defer fmt.gpa.free(source_code);
722752
723 const tree = std.zig.parse(fmt.gpa, source_code) catch |err| {
724 std.debug.warn("error parsing file '{}': {}\n", .{ file_path, err });
725 fmt.any_error = true;
726 return;
727 };
753 // Add to set after no longer possible to get error.IsDir.
754 if (try fmt.seen.put(stat.inode, {})) |_| return;
755
756 const tree = try std.zig.parse(fmt.gpa, source_code);
728757 defer tree.deinit();
729758
730759 for (tree.errors) |parse_error| {
......@@ -742,14 +771,19 @@ fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void {
742771 fmt.any_error = true;
743772 }
744773 } else {
745 const baf = try io.BufferedAtomicFile.create(fmt.gpa, fs.cwd(), real_path, .{ .mode = stat.mode });
746 defer baf.destroy();
747
748 const anything_changed = try std.zig.render(fmt.gpa, baf.stream(), tree);
749 if (anything_changed) {
750 std.debug.warn("{}\n", .{file_path});
751 try baf.finish();
752 }
774 // As a heuristic, we make enough capacity for the same as the input source.
775 try fmt.out_buffer.ensureCapacity(source_code.len);
776 fmt.out_buffer.items.len = 0;
777 const anything_changed = try std.zig.render(fmt.gpa, fmt.out_buffer.writer(), tree);
778 if (!anything_changed)
779 return; // Good thing we didn't waste any file system access on this.
780
781 var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode });
782 defer af.deinit();
783
784 try af.file.writeAll(fmt.out_buffer.items);
785 try af.finish();
786 std.debug.warn("{}\n", .{file_path});
753787 }
754788}
755789